WIP
This commit is contained in:
parent
d8c0371d43
commit
437644584a
|
@ -4,6 +4,7 @@ import router from '~/router'
|
||||||
import App from '~/components/App.vue'
|
import App from '~/components/App.vue'
|
||||||
import Base from './base.js'
|
import Base from './base.js'
|
||||||
import registerPlugin from './plugins'
|
import registerPlugin from './plugins'
|
||||||
|
import { registerComponents } from './components'
|
||||||
|
|
||||||
import '~/plugins'
|
import '~/plugins'
|
||||||
import '~/components'
|
import '~/components'
|
||||||
|
@ -16,10 +17,15 @@ const app = createApp(App)
|
||||||
.mixin(Base)
|
.mixin(Base)
|
||||||
|
|
||||||
registerPlugin(app)
|
registerPlugin(app)
|
||||||
|
registerComponents(app)
|
||||||
|
|
||||||
configureCompat({
|
configureCompat({
|
||||||
// default everything to Vue 2 behavior
|
// default everything to Vue 2 behavior
|
||||||
MODE: 2
|
MODE: 2,
|
||||||
|
GLOBAL_MOUNT: false,
|
||||||
|
COMPONENT_V_MODEL: false,
|
||||||
|
INSTANCE_SET: false,
|
||||||
|
INSTANCE_DELETE: false
|
||||||
})
|
})
|
||||||
|
|
||||||
router.app = app
|
router.app = app
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="sm:flex sm:flex-col sm:items-start">
|
<div class="sm:flex sm:flex-col sm:items-start">
|
||||||
<div v-if="$scopedSlots.hasOwnProperty('icon')" class="flex w-full justify-center mb-4">
|
<div v-if="$slots.hasOwnProperty('icon')" class="flex w-full justify-center mb-4">
|
||||||
<div class="w-14 h-14 rounded-full flex justify-center items-center"
|
<div class="w-14 h-14 rounded-full flex justify-center items-center"
|
||||||
:class="'bg-'+iconColor+'-100 text-'+iconColor+'-600'"
|
:class="'bg-'+iconColor+'-100 text-'+iconColor+'-600'"
|
||||||
>
|
>
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3 text-center sm:mt-0 w-full">
|
<div class="mt-3 text-center sm:mt-0 w-full">
|
||||||
<h2 v-if="$scopedSlots.hasOwnProperty('title')"
|
<h2 v-if="$slots.hasOwnProperty('title')"
|
||||||
class="text-2xl font-semibold text-center text-gray-900"
|
class="text-2xl font-semibold text-center text-gray-900"
|
||||||
>
|
>
|
||||||
<slot name="title" />
|
<slot name="title" />
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="$scopedSlots.hasOwnProperty('footer')" class="px-6 py-4 bg-gray-100 text-right">
|
<div v-if="$slots.hasOwnProperty('footer')" class="px-6 py-4 bg-gray-100 text-right">
|
||||||
<slot name="footer" />
|
<slot name="footer" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -120,17 +120,11 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
created () {
|
created () {
|
||||||
const closeOnEscape = (e) => {
|
document.addEventListener('keydown', this.closeOnEscape)
|
||||||
if (e.key === 'Escape' && this.show) {
|
},
|
||||||
this.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('keydown', closeOnEscape)
|
beforeUnmount () {
|
||||||
|
document.removeEventListener('keydown', this.closeOnEscape)
|
||||||
this.$once('hook:unmounted', () => {
|
|
||||||
document.removeEventListener('keydown', closeOnEscape)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -143,6 +137,11 @@ export default {
|
||||||
if (this.afterLeave) {
|
if (this.afterLeave) {
|
||||||
this.afterLeave()
|
this.afterLeave()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
closeOnEscape (e) {
|
||||||
|
if (e.key === 'Escape' && this.show) {
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,34 +15,27 @@
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<v-transition>
|
<VTransition>
|
||||||
<div v-if="showContent" class="w-full">
|
<div v-if="showContent" class="w-full">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</v-transition>
|
</VTransition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import VTransition from './transitions/VTransition.vue'
|
import VTransition from './transitions/VTransition.vue'
|
||||||
|
import { ref, defineProps, defineEmits } from 'vue'
|
||||||
|
|
||||||
export default {
|
const props = defineProps({
|
||||||
name: 'Collapse',
|
modelValue: { type: Boolean, default: null }
|
||||||
components: { VTransition },
|
})
|
||||||
props: {
|
|
||||||
defaultValue: { type: Boolean, default: false },
|
const showContent = ref(props.modelValue)
|
||||||
value: { type: Boolean, default: null }
|
const emit = defineEmits()
|
||||||
},
|
|
||||||
data () {
|
const trigger = () => {
|
||||||
return {
|
showContent.value = !showContent.value
|
||||||
showContent: this.value ?? this.defaultValue
|
emit('update:modelValue', showContent.value)
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
trigger () {
|
|
||||||
this.showContent = !this.showContent
|
|
||||||
this.$emit('input', this.showContent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import Vue from 'vue'
|
|
||||||
|
|
||||||
import Dropdown from './Dropdown.vue'
|
import Dropdown from './Dropdown.vue'
|
||||||
import Card from './Card.vue'
|
import Card from './Card.vue'
|
||||||
import Button from './Button.vue'
|
import Button from './Button.vue'
|
||||||
// Components that are registered globaly.
|
export function registerComponents (app) {
|
||||||
[
|
[
|
||||||
Card,
|
Card,
|
||||||
Button,
|
Button,
|
||||||
Dropdown
|
Dropdown
|
||||||
].forEach(Component => {
|
].forEach(Component => {
|
||||||
Vue.component(Component.name, Component)
|
app.component(Component.name, Component)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ export default {
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
clearUrl () {
|
clearUrl () {
|
||||||
this.$set(this.form, this.name, null)
|
this.form[this.name] = null
|
||||||
},
|
},
|
||||||
onUploadDragoverEvent (e) {
|
onUploadDragoverEvent (e) {
|
||||||
this.uploadDragoverEvent = true
|
this.uploadDragoverEvent = true
|
||||||
|
|
|
@ -50,11 +50,11 @@ export default {
|
||||||
this.onEnd()
|
this.onEnd()
|
||||||
},
|
},
|
||||||
onEnd () {
|
onEnd () {
|
||||||
if(this.disabled){
|
if (this.disabled) {
|
||||||
this.$refs.signaturePad.clearSignature()
|
this.$refs.signaturePad.clearSignature()
|
||||||
}else{
|
} else {
|
||||||
const { isEmpty, data } = this.$refs.signaturePad.saveSignature()
|
const { isEmpty, data } = this.$refs.signaturePad.saveSignature()
|
||||||
this.$set(this.form, this.name, (!isEmpty && data) ? data : null)
|
this.form[this.name] = (!isEmpty && data) ? data : null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="wrapperClass" :style="inputStyle">
|
<input-wrapper
|
||||||
<slot name="label">
|
v-bind="$props"
|
||||||
<input-label v-if="label"
|
>
|
||||||
:label="label"
|
<template #label>
|
||||||
:theme="theme"
|
<slot name="label" />
|
||||||
:required="true"
|
</template>
|
||||||
:native-for="id?id:name"
|
<template v-if="helpPosition==='above_input'" #help>
|
||||||
:uppercase-labels="uppercaseLabels"
|
|
||||||
/>
|
|
||||||
</slot>
|
|
||||||
<input-help v-if="help && helpPosition=='above_input'" :help="help" :theme="theme">
|
|
||||||
<template #help>
|
|
||||||
<slot name="help" />
|
<slot name="help" />
|
||||||
</template>
|
</template>
|
||||||
</input-help>
|
|
||||||
<input :id="id?id:name" v-model="compVal" :disabled="disabled"
|
<input :id="id?id:name" v-model="compVal" :disabled="disabled"
|
||||||
:type="nativeType"
|
:type="nativeType"
|
||||||
:pattern="pattern"
|
:pattern="pattern"
|
||||||
|
@ -23,25 +18,34 @@
|
||||||
:placeholder="placeholder" :min="min" :max="max" :maxlength="maxCharLimit"
|
:placeholder="placeholder" :min="min" :max="max" :maxlength="maxCharLimit"
|
||||||
@change="onChange" @keydown.enter.prevent="onEnterPress"
|
@change="onChange" @keydown.enter.prevent="onEnterPress"
|
||||||
>
|
>
|
||||||
<!-- <input-help v-if="(help && helpPosition=='below_input') || showCharLimit" :help="help" :theme="theme">-->
|
|
||||||
|
<!-- TODO: fix this in the case of below input there's something off -->
|
||||||
|
<!-- <input-help v-if="helpPosition==='below_input' || showCharLimit" :help="help" :theme="theme">-->
|
||||||
|
<!-- <template #help>-->
|
||||||
|
<!-- <slot name="help" />-->
|
||||||
|
<!-- </template>-->
|
||||||
<!-- <template v-if="showCharLimit" #after-help>-->
|
<!-- <template v-if="showCharLimit" #after-help>-->
|
||||||
<!-- <small v-if="showCharLimit && maxCharLimit" :class="theme.default.help">-->
|
<!-- <small v-if="showCharLimit && maxCharLimit" :class="theme.default.help">-->
|
||||||
<!-- {{ charCount }}/{{ maxCharLimit }}-->
|
<!-- {{ charCount }}/{{ maxCharLimit }}-->
|
||||||
<!-- </small>-->
|
<!-- </small>-->
|
||||||
<!-- </template>-->
|
<!-- </template>-->
|
||||||
<!-- </input-help>-->
|
<!-- </input-help>-->
|
||||||
<has-error v-if="hasValidation" :form="form" :field="name" />
|
|
||||||
</div>
|
<template #error>
|
||||||
|
<slot name="error" />
|
||||||
|
</template>
|
||||||
|
</input-wrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { inputProps, useFormInput } from './useFormInput.js'
|
import { inputProps, useFormInput } from './useFormInput.js'
|
||||||
import InputLabel from './components/InputLabel.vue'
|
import InputLabel from './components/InputLabel.vue'
|
||||||
import InputHelp from './components/InputHelp.vue'
|
import InputHelp from './components/InputHelp.vue'
|
||||||
|
import InputWrapper from './components/InputWrapper.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TextInput',
|
name: 'TextInput',
|
||||||
components: { InputHelp, InputLabel },
|
components: { InputWrapper, InputHelp, InputLabel },
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
...inputProps,
|
...inputProps,
|
||||||
|
@ -54,11 +58,15 @@ export default {
|
||||||
pattern: { type: String, default: null }
|
pattern: { type: String, default: null }
|
||||||
},
|
},
|
||||||
|
|
||||||
setup (props) {
|
setup (props, context) {
|
||||||
const { compVal, inputStyle, hasValidation, hasError } = useFormInput(props)
|
const {
|
||||||
|
compVal,
|
||||||
|
inputStyle,
|
||||||
|
hasValidation,
|
||||||
|
hasError
|
||||||
|
} = useFormInput(props, context, props.nativeType === 'file' ? 'file-' : null)
|
||||||
|
|
||||||
const onChange = (event) => {
|
const onChange = (event) => {
|
||||||
console.log(props)
|
|
||||||
if (props.nativeType !== 'file') return
|
if (props.nativeType !== 'file') return
|
||||||
|
|
||||||
const file = event.target.files[0]
|
const file = event.target.files[0]
|
||||||
|
@ -77,6 +85,11 @@ export default {
|
||||||
hasValidation,
|
hasValidation,
|
||||||
hasError
|
hasError
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
charCount () {
|
||||||
|
return (this.compVal) ? this.compVal.length : 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,36 +1,50 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="wrapperClass">
|
<div :class="wrapperClass">
|
||||||
<small v-if="help && helpPosition=='above_input'" :class="theme.default.help" class="flex mb-1">
|
<input-help v-if="help && helpPosition=='above_input'" :help="help" :theme="theme">
|
||||||
<slot name="help"><span class="field-help" v-html="help" /></slot>
|
<template #help>
|
||||||
</small>
|
<slot name="help" />
|
||||||
|
</template>
|
||||||
|
</input-help>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<v-switch :id="id?id:name" v-model="compVal" class="inline-block mr-2" :disabled="disabled" :name="name" @input="$emit('input',$event)" />
|
<v-switch :id="id?id:name" v-model="compVal" class="inline-block mr-2" :disabled="disabled" />
|
||||||
<slot name="label">
|
<slot name="label">
|
||||||
<span>{{ label }} <span v-if="required" class="text-red-500 required-dot">*</span></span>
|
<span>{{ label }} <span v-if="required" class="text-red-500 required-dot">*</span></span>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
<small v-if="help && helpPosition=='below_input'" :class="theme.default.help">
|
<input-help v-if="help && helpPosition=='below_input'" :help="help" :theme="theme">
|
||||||
<slot name="help"><span class="field-help" v-html="help" /></slot>
|
<template #help>
|
||||||
</small>
|
<slot name="help" />
|
||||||
|
</template>
|
||||||
|
</input-help>
|
||||||
<has-error v-if="hasValidation" :form="form" :field="name" />
|
<has-error v-if="hasValidation" :form="form" :field="name" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import inputMixin from '~/mixins/forms/input.js'
|
import { inputProps, useFormInput } from './useFormInput.js'
|
||||||
|
import InputHelp from './components/InputHelp.vue'
|
||||||
import VSwitch from './components/VSwitch.vue'
|
import VSwitch from './components/VSwitch.vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'ToggleSwitchInput',
|
name: 'ToggleSwitchInput',
|
||||||
|
|
||||||
components: { VSwitch },
|
components: { InputHelp, VSwitch },
|
||||||
mixins: [inputMixin],
|
props: {
|
||||||
props: {},
|
...inputProps
|
||||||
|
},
|
||||||
|
|
||||||
|
setup (props, context) {
|
||||||
|
const { compVal, inputStyle, hasValidation, hasError } = useFormInput(props, context)
|
||||||
|
|
||||||
|
return {
|
||||||
|
compVal,
|
||||||
|
inputStyle,
|
||||||
|
hasValidation,
|
||||||
|
hasError
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
mounted () {
|
mounted () {
|
||||||
this.compVal = !!this.compVal
|
this.compVal = !!this.compVal
|
||||||
this.$emit('input', !!this.compVal)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex mb-1">
|
<div class="flex mb-1 input-help">
|
||||||
<small :class="theme.default.help" class="grow flex">
|
<small :class="theme.default.help" class="grow flex">
|
||||||
<slot name="help"><span class="field-help" v-html="help" /></slot>
|
<slot name="help"><span class="field-help" v-html="help" /></slot>
|
||||||
</small>
|
</small>
|
||||||
|
@ -15,7 +15,7 @@ export default {
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
theme: { type: Object, required: true },
|
theme: { type: Object, required: true },
|
||||||
help: { type: String, required: true }
|
help: { type: String, required: false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<label :for="nativeFor"
|
<label :for="nativeFor"
|
||||||
|
class="input-label"
|
||||||
:class="[theme.default.label,{'uppercase text-xs': uppercaseLabels, 'text-sm': !uppercaseLabels}]"
|
:class="[theme.default.label,{'uppercase text-xs': uppercaseLabels, 'text-sm': !uppercaseLabels}]"
|
||||||
>
|
>
|
||||||
|
<slot>
|
||||||
{{ label }}
|
{{ label }}
|
||||||
<span v-if="required" class="text-red-500 required-dot">*</span>
|
<span v-if="required" class="text-red-500 required-dot">*</span>
|
||||||
|
</slot>
|
||||||
</label>
|
</label>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
<template>
|
||||||
|
<div :class="wrapperClass" :style="inputStyle">
|
||||||
|
<slot name="label">
|
||||||
|
<input-label v-if="label"
|
||||||
|
:label="label"
|
||||||
|
:theme="theme"
|
||||||
|
:required="true"
|
||||||
|
:native-for="id?id:name"
|
||||||
|
:uppercase-labels="uppercaseLabels"
|
||||||
|
/>
|
||||||
|
</slot>
|
||||||
|
<slot v-if="help && helpPosition==='above_input'" name="help">
|
||||||
|
<input-help :help="help" :theme="theme" />
|
||||||
|
</slot>
|
||||||
|
<slot />
|
||||||
|
<slot v-if="help && helpPosition==='below_input'" name="help">
|
||||||
|
<input-help :help="help" :theme="theme" />
|
||||||
|
</slot>
|
||||||
|
<slot name="error">
|
||||||
|
<has-error v-if="hasValidation" :form="form" :field="name" />
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import InputLabel from './InputLabel.vue'
|
||||||
|
import InputHelp from './InputHelp.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'InputWrapper',
|
||||||
|
components: { InputLabel, InputHelp },
|
||||||
|
|
||||||
|
props: {
|
||||||
|
id: { type: String, required: false },
|
||||||
|
name: { type: String, required: false },
|
||||||
|
theme: { type: Object, required: true },
|
||||||
|
wrapperClass: { type: String, required: false },
|
||||||
|
inputStyle: { type: Object, required: false },
|
||||||
|
help: { type: String, required: false },
|
||||||
|
label: { type: String, required: false },
|
||||||
|
helpPosition: { type: String, default: 'below_input' },
|
||||||
|
uppercaseLabels: { type: Boolean, default: true },
|
||||||
|
hasValidation: { type: Boolean, default: true },
|
||||||
|
form: { type: Object, required: false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,45 +1,23 @@
|
||||||
<template>
|
<template>
|
||||||
<div @click="onClick">
|
<div role="button" @click="onClick">
|
||||||
<div class="inline-flex items-center h-6 w-12 p-1 bg-gray-300 border rounded-full cursor-pointer focus:outline-none transition-all transform ease-in-out duration-100" :class="{'bg-nt-blue': internalValue}">
|
<div class="inline-flex items-center h-6 w-12 p-1 bg-gray-300 border rounded-full cursor-pointer focus:outline-none transition-all transform ease-in-out duration-100" :class="{'bg-nt-blue': modelValue}">
|
||||||
<div class="inline-block h-4 w-4 rounded-full bg-white shadow transition-all transform ease-in-out duration-150 rounded-2xl scale-100" :class="{'translate-x-5.5': internalValue}" />
|
<div class="inline-block h-4 w-4 rounded-full bg-white shadow transition-all transform ease-in-out duration-150 rounded-2xl scale-100" :class="{'translate-x-5.5': modelValue}" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
import { defineProps, defineEmits } from 'vue'
|
||||||
name: 'VSwitch',
|
|
||||||
components: { },
|
|
||||||
|
|
||||||
props: {
|
const { modelValue, disabled } = defineProps({
|
||||||
value: { type: Boolean, default: false },
|
modelValue: { type: Boolean, default: false },
|
||||||
disabled: { type: Boolean, default: false }
|
disabled: { type: Boolean, default: false }
|
||||||
},
|
})
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
data () {
|
const onClick = () => {
|
||||||
return {
|
if (disabled) return
|
||||||
internalValue: this.value
|
console.log('ok emiting', !modelValue)
|
||||||
}
|
emit('update:modelValue', !modelValue)
|
||||||
},
|
|
||||||
|
|
||||||
computed: {},
|
|
||||||
|
|
||||||
watch: {
|
|
||||||
value (val) {
|
|
||||||
this.internalValue = val
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted () {
|
|
||||||
this.internalValue = this.value
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
onClick () {
|
|
||||||
if(this.disabled) return
|
|
||||||
this.$emit('input', !this.internalValue)
|
|
||||||
this.internalValue = !this.internalValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
|
@ -1,4 +1,4 @@
|
||||||
import Vue from 'vue'
|
import { defineAsyncComponent } from 'vue'
|
||||||
|
|
||||||
import HasError from './validation/HasError.vue'
|
import HasError from './validation/HasError.vue'
|
||||||
import AlertError from './validation/AlertError.vue'
|
import AlertError from './validation/AlertError.vue'
|
||||||
|
@ -16,8 +16,8 @@ import RatingInput from './RatingInput.vue'
|
||||||
import FlatSelectInput from './FlatSelectInput.vue'
|
import FlatSelectInput from './FlatSelectInput.vue'
|
||||||
import ToggleSwitchInput from './ToggleSwitchInput.vue'
|
import ToggleSwitchInput from './ToggleSwitchInput.vue'
|
||||||
|
|
||||||
// Components that are registered globaly.
|
export function registerComponents (app) {
|
||||||
[
|
[
|
||||||
HasError,
|
HasError,
|
||||||
AlertError,
|
AlertError,
|
||||||
AlertSuccess,
|
AlertSuccess,
|
||||||
|
@ -33,12 +33,21 @@ import ToggleSwitchInput from './ToggleSwitchInput.vue'
|
||||||
RatingInput,
|
RatingInput,
|
||||||
FlatSelectInput,
|
FlatSelectInput,
|
||||||
ToggleSwitchInput
|
ToggleSwitchInput
|
||||||
].forEach(Component => {
|
].forEach(Component => {
|
||||||
Vue.component(Component.name, Component)
|
app.component(Component.name, Component)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Lazy load some heavy component
|
// Register async components
|
||||||
Vue.component('SignatureInput', () => import('./SignatureInput.vue'))
|
app.component('SignatureInput', defineAsyncComponent(() =>
|
||||||
Vue.component('RichTextAreaInput', () => import('./RichTextAreaInput.vue'))
|
import('./SignatureInput.vue')
|
||||||
Vue.component('DateInput', () => import('./DateInput.vue'))
|
))
|
||||||
Vue.component('PhoneInput', () => import('./PhoneInput.vue'))
|
app.component('RichTextAreaInput', defineAsyncComponent(() =>
|
||||||
|
import('./RichTextAreaInput.vue')
|
||||||
|
))
|
||||||
|
app.component('PhoneInput', defineAsyncComponent(() =>
|
||||||
|
import('./PhoneInput.vue')
|
||||||
|
))
|
||||||
|
app.component('DateInput', defineAsyncComponent(() =>
|
||||||
|
import('./DateInput.vue')
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ref, computed, watch, defineEmits } from 'vue'
|
import { ref, computed, watch } from 'vue'
|
||||||
import { themes } from '~/config/form-themes.js'
|
import { themes } from '~/config/form-themes.js'
|
||||||
|
|
||||||
export const inputProps = {
|
export const inputProps = {
|
||||||
|
@ -18,7 +18,7 @@ export const inputProps = {
|
||||||
wrapperClass: { type: String, default: 'relative mb-3' }
|
wrapperClass: { type: String, default: 'relative mb-3' }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useFormInput (props) {
|
export function useFormInput (props, context, formPrefixKey = null) {
|
||||||
const content = ref(props.modelValue)
|
const content = ref(props.modelValue)
|
||||||
|
|
||||||
const inputStyle = computed(() => {
|
const inputStyle = computed(() => {
|
||||||
|
@ -38,13 +38,13 @@ export function useFormInput (props) {
|
||||||
const compVal = computed({
|
const compVal = computed({
|
||||||
get: () => {
|
get: () => {
|
||||||
if (props.form) {
|
if (props.form) {
|
||||||
return props.form[props.name]
|
return props.form[(formPrefixKey || '') + props.name]
|
||||||
}
|
}
|
||||||
return content.value
|
return content.value
|
||||||
},
|
},
|
||||||
set: (val) => {
|
set: (val) => {
|
||||||
if (props.form) {
|
if (props.form) {
|
||||||
props.form[props.name] = val
|
props.form[(formPrefixKey || '') + props.name] = val
|
||||||
} else {
|
} else {
|
||||||
content.value = val
|
content.value = val
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ export function useFormInput (props) {
|
||||||
props.form.errors.clear(props.name)
|
props.form.errors.clear(props.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
defineEmits('update:modelValue', compVal.value)
|
context.emit('update:modelValue', compVal.value)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,24 @@
|
||||||
import './common'
|
import { defineAsyncComponent } from 'vue'
|
||||||
import './forms'
|
import { registerComponents as registerCommonComponents } from './common'
|
||||||
|
import { registerComponents as registerFormComponents } from './forms'
|
||||||
|
|
||||||
import Vue from 'vue'
|
|
||||||
import Child from './Child.vue'
|
import Child from './Child.vue'
|
||||||
import Modal from './Modal.vue'
|
import Modal from './Modal.vue'
|
||||||
|
|
||||||
import Loader from './common/Loader.vue'
|
import Loader from './common/Loader.vue'
|
||||||
|
|
||||||
// Components that are registered globaly.
|
export function registerComponents (app) {
|
||||||
[
|
[Child, Modal, Loader].forEach(Component => {
|
||||||
Child,
|
app.component(Component.name, Component)
|
||||||
Modal,
|
})
|
||||||
Loader
|
|
||||||
].forEach(Component => {
|
|
||||||
Vue.component(Component.name, Component)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Lazy load some heavy component
|
registerCommonComponents(app)
|
||||||
Vue.component('FormEditor', () => import('./open/forms/components/FormEditor.vue'))
|
registerFormComponents(app)
|
||||||
Vue.component('NotionPage', () => import('./open/NotionPage.vue'))
|
|
||||||
|
// Register async components
|
||||||
|
app.component('FormEditor', defineAsyncComponent(() =>
|
||||||
|
import('./open/forms/components/FormEditor.vue')
|
||||||
|
))
|
||||||
|
app.component('NotionPage', defineAsyncComponent(() =>
|
||||||
|
import('./open/NotionPage.vue')
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<collapse class="py-5 w-full" :default-value="false">
|
<collapse class="py-5 w-full" :model-value="false">
|
||||||
<template #title>
|
<template #title>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<h3 class="font-semibold block text-lg">
|
<h3 class="font-semibold block text-lg">
|
||||||
|
@ -12,8 +12,8 @@
|
||||||
<toggle-switch-input :value="value.hide_title" name="hide_title" class="mt-4"
|
<toggle-switch-input :value="value.hide_title" name="hide_title" class="mt-4"
|
||||||
label="Hide Form Title"
|
label="Hide Form Title"
|
||||||
:disabled="form.hide_title===true"
|
:disabled="form.hide_title===true"
|
||||||
@input="onChangeHideTitle"
|
|
||||||
:help="hideTitleHelp"
|
:help="hideTitleHelp"
|
||||||
|
@input="onChangeHideTitle"
|
||||||
/>
|
/>
|
||||||
<toggle-switch-input :value="value.auto_submit" name="auto_submit" class="mt-4"
|
<toggle-switch-input :value="value.auto_submit" name="auto_submit" class="mt-4"
|
||||||
label="Auto Submit Form"
|
label="Auto Submit Form"
|
||||||
|
|
|
@ -205,7 +205,7 @@ export default {
|
||||||
formFields: {
|
formFields: {
|
||||||
deep: true,
|
deep: true,
|
||||||
handler () {
|
handler () {
|
||||||
this.$set(this.form, 'properties', this.formFields)
|
this.form.properties = this.formFields
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -228,21 +228,21 @@ export default {
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onChangeName (field, newName) {
|
onChangeName (field, newName) {
|
||||||
this.$set(field, 'name', newName)
|
field.name = newName
|
||||||
},
|
},
|
||||||
toggleHidden (field) {
|
toggleHidden (field) {
|
||||||
this.$set(field, 'hidden', !field.hidden)
|
field.hidden = !field.hidden
|
||||||
if (field.hidden) {
|
if (field.hidden) {
|
||||||
this.$set(field, 'required', false)
|
field.required = false
|
||||||
} else {
|
} else {
|
||||||
this.$set(field, 'generates_uuid', false)
|
field.generates_uuid = false
|
||||||
this.$set(field, 'generates_auto_increment_id', false)
|
field.generates_auto_increment_id = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
toggleRequired (field) {
|
toggleRequired (field) {
|
||||||
this.$set(field, 'required', !field.required)
|
field.required = !field.required
|
||||||
if (field.required) {
|
if (field.required) {
|
||||||
this.$set(field, 'hidden', false)
|
field.hidden = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getDefaultFields () {
|
getDefaultFields () {
|
||||||
|
@ -283,7 +283,7 @@ export default {
|
||||||
return field
|
return field
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.$set(this.form, 'properties', this.formFields)
|
this.form.properties = this.formFields
|
||||||
},
|
},
|
||||||
generateUUID () {
|
generateUUID () {
|
||||||
let d = new Date().getTime()// Timestamp
|
let d = new Date().getTime()// Timestamp
|
||||||
|
@ -318,7 +318,7 @@ export default {
|
||||||
removeBlock (blockIndex) {
|
removeBlock (blockIndex) {
|
||||||
const newFields = clonedeep(this.formFields)
|
const newFields = clonedeep(this.formFields)
|
||||||
newFields.splice(blockIndex, 1)
|
newFields.splice(blockIndex, 1)
|
||||||
this.$set(this, 'formFields', newFields)
|
this.formFields = newFields
|
||||||
this.closeSidebar()
|
this.closeSidebar()
|
||||||
},
|
},
|
||||||
closeSidebar () {
|
closeSidebar () {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="my-4 w-full mx-auto">
|
class="my-4 w-full mx-auto"
|
||||||
|
>
|
||||||
<h3 class="font-semibold mb-4 text-xl">
|
<h3 class="font-semibold mb-4 text-xl">
|
||||||
Form Submissions
|
Form Submissions
|
||||||
</h3>
|
</h3>
|
||||||
|
@ -9,8 +10,8 @@
|
||||||
<modal :show="showColumnsModal" @close="showColumnsModal=false">
|
<modal :show="showColumnsModal" @close="showColumnsModal=false">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<svg class="w-8 h-8" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="w-8 h-8" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M16 5H8C4.13401 5 1 8.13401 1 12C1 15.866 4.13401 19 8 19H16C19.866 19 23 15.866 23 12C23 8.13401 19.866 5 16 5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M16 5H8C4.13401 5 1 8.13401 1 12C1 15.866 4.13401 19 8 19H16C19.866 19 23 15.866 23 12C23 8.13401 19.866 5 16 5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
<path d="M8 15C9.65685 15 11 13.6569 11 12C11 10.3431 9.65685 9 8 9C6.34315 9 5 10.3431 5 12C5 13.6569 6.34315 15 8 15Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M8 15C9.65685 15 11 13.6569 11 12C11 10.3431 9.65685 9 8 9C6.34315 9 5 10.3431 5 12C5 13.6569 6.34315 15 8 15Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
<template #title>
|
<template #title>
|
||||||
|
@ -19,33 +20,43 @@
|
||||||
|
|
||||||
<div class="px-4">
|
<div class="px-4">
|
||||||
<template v-if="properties.length > 0">
|
<template v-if="properties.length > 0">
|
||||||
<h4 class="font-bold mb-2">Form Fields</h4>
|
<h4 class="font-bold mb-2">
|
||||||
|
Form Fields
|
||||||
|
</h4>
|
||||||
<div v-for="field in properties" :key="field.id" class="p-2 border">
|
<div v-for="field in properties" :key="field.id" class="p-2 border">
|
||||||
{{ field.name }}
|
{{ field.name }}
|
||||||
<v-switch v-model="displayColumns[field.id]" @input="onChangeDisplayColumns" class="float-right"/>
|
<v-switch v-model="displayColumns[field.id]" class="float-right" @input="onChangeDisplayColumns" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="removed_properties.length > 0">
|
<template v-if="removed_properties.length > 0">
|
||||||
<h4 class="font-bold mb-2 mt-4">Removed Fields</h4>
|
<h4 class="font-bold mb-2 mt-4">
|
||||||
|
Removed Fields
|
||||||
|
</h4>
|
||||||
<div v-for="field in removed_properties" :key="field.id" class="p-2 border">
|
<div v-for="field in removed_properties" :key="field.id" class="p-2 border">
|
||||||
{{ field.name }}
|
{{ field.name }}
|
||||||
<v-switch v-model="displayColumns[field.id]" @input="onChangeDisplayColumns" class="float-right"/>
|
<v-switch v-model="displayColumns[field.id]" class="float-right" @input="onChangeDisplayColumns" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</modal>
|
</modal>
|
||||||
|
|
||||||
<loader v-if="!form || isLoading" class="h-6 w-6 text-nt-blue mx-auto"/>
|
<loader v-if="!form || isLoading" class="h-6 w-6 text-nt-blue mx-auto" />
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<div class="flex flex-wrap items-end">
|
<div class="flex flex-wrap items-end">
|
||||||
<div class="flex-grow">
|
<div class="flex-grow">
|
||||||
<text-input class="w-64" :form="searchForm" name="search" placeholder="Search..." />
|
<text-input class="w-64" :form="searchForm" name="search" placeholder="Search..." />
|
||||||
</div>
|
</div>
|
||||||
<div class="font-semibold flex gap-4">
|
<div class="font-semibold flex gap-4">
|
||||||
<p v-if="form && !isLoading && formInitDone" class="float-right text-xs uppercase mb-2"> <a
|
<p v-if="form && !isLoading && formInitDone" class="float-right text-xs uppercase mb-2">
|
||||||
href="javascript:void(0);" class="text-gray-500" @click="showColumnsModal=true">Display columns</a></p>
|
<a
|
||||||
<p v-if="form && !isLoading && tableData.length > 0" class="text-right text-xs uppercase"><a
|
href="javascript:void(0);" class="text-gray-500" @click="showColumnsModal=true"
|
||||||
:href="exportUrl" target="_blank">Export as CSV</a></p>
|
>Display columns</a>
|
||||||
|
</p>
|
||||||
|
<p v-if="form && !isLoading && tableData.length > 0" class="text-right text-xs uppercase">
|
||||||
|
<a
|
||||||
|
:href="exportUrl" target="_blank"
|
||||||
|
>Export as CSV</a>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -62,8 +73,7 @@
|
||||||
:loading="isLoading"
|
:loading="isLoading"
|
||||||
@resize="dataChanged()"
|
@resize="dataChanged()"
|
||||||
@deleted="onDeleteRecord()"
|
@deleted="onDeleteRecord()"
|
||||||
>
|
/>
|
||||||
</open-table>
|
|
||||||
</scroll-shadow>
|
</scroll-shadow>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -75,14 +85,14 @@ import Fuse from 'fuse.js'
|
||||||
import Form from 'vform'
|
import Form from 'vform'
|
||||||
import ScrollShadow from '../../../common/ScrollShadow.vue'
|
import ScrollShadow from '../../../common/ScrollShadow.vue'
|
||||||
import OpenTable from '../../tables/OpenTable.vue'
|
import OpenTable from '../../tables/OpenTable.vue'
|
||||||
import clonedeep from "clone-deep";
|
import clonedeep from 'clone-deep'
|
||||||
import VSwitch from '../../../forms/components/VSwitch.vue'
|
import VSwitch from '../../../forms/components/VSwitch.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'FormSubmissions',
|
name: 'FormSubmissions',
|
||||||
components: {ScrollShadow, OpenTable, VSwitch},
|
components: { ScrollShadow, OpenTable, VSwitch },
|
||||||
props: {},
|
props: {},
|
||||||
data() {
|
data () {
|
||||||
return {
|
return {
|
||||||
formInitDone: false,
|
formInitDone: false,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
|
@ -98,38 +108,25 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
this.initFormStructure()
|
|
||||||
this.getSubmissionsData()
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
form() {
|
|
||||||
if (this.form === null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.initFormStructure()
|
|
||||||
this.getSubmissionsData()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
form: {
|
form: {
|
||||||
get() {
|
get () {
|
||||||
return this.$store.state['open/working_form'].content
|
return this.$store.state['open/working_form'].content
|
||||||
},
|
},
|
||||||
set(value) {
|
set (value) {
|
||||||
this.$store.commit('open/working_form/set', value)
|
this.$store.commit('open/working_form/set', value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
exportUrl() {
|
exportUrl () {
|
||||||
if (!this.form) {
|
if (!this.form) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
return '/api/open/forms/' + this.form.id + '/submissions/export'
|
return '/api/open/forms/' + this.form.id + '/submissions/export'
|
||||||
},
|
},
|
||||||
filteredData () {
|
filteredData () {
|
||||||
if(!this.tableData) return []
|
if (!this.tableData) return []
|
||||||
|
|
||||||
let filteredData = clonedeep(this.tableData)
|
const filteredData = clonedeep(this.tableData)
|
||||||
|
|
||||||
if (this.searchForm.search === '' || this.searchForm.search === null) {
|
if (this.searchForm.search === '' || this.searchForm.search === null) {
|
||||||
return filteredData
|
return filteredData
|
||||||
|
@ -145,8 +142,21 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
form () {
|
||||||
|
if (this.form === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.initFormStructure()
|
||||||
|
this.getSubmissionsData()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.initFormStructure()
|
||||||
|
this.getSubmissionsData()
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initFormStructure() {
|
initFormStructure () {
|
||||||
if (!this.form || this.formInitDone) {
|
if (!this.form || this.formInitDone) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -163,12 +173,12 @@ export default {
|
||||||
// Add a "created at" column
|
// Add a "created at" column
|
||||||
const columns = clonedeep(this.form.properties)
|
const columns = clonedeep(this.form.properties)
|
||||||
columns.push({
|
columns.push({
|
||||||
"name": "Created at",
|
name: 'Created at',
|
||||||
"id": "created_at",
|
id: 'created_at',
|
||||||
"type": "date",
|
type: 'date',
|
||||||
"width": 140,
|
width: 140
|
||||||
})
|
})
|
||||||
this.$set(this.form, 'properties', columns)
|
this.form.properties = columns
|
||||||
}
|
}
|
||||||
this.formInitDone = true
|
this.formInitDone = true
|
||||||
|
|
||||||
|
@ -186,7 +196,7 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getSubmissionsData() {
|
getSubmissionsData () {
|
||||||
if (!this.form || this.fullyLoaded) {
|
if (!this.form || this.fullyLoaded) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -208,24 +218,23 @@ export default {
|
||||||
this.isLoading = false
|
this.isLoading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
dataChanged() {
|
dataChanged () {
|
||||||
if (this.$refs.shadows) {
|
if (this.$refs.shadows) {
|
||||||
this.$refs.shadows.toggleShadow()
|
this.$refs.shadows.toggleShadow()
|
||||||
this.$refs.shadows.calcDimensions()
|
this.$refs.shadows.calcDimensions()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onChangeDisplayColumns() {
|
onChangeDisplayColumns () {
|
||||||
window.localStorage.setItem('display-columns-formid-' + this.form.id, JSON.stringify(this.displayColumns))
|
window.localStorage.setItem('display-columns-formid-' + this.form.id, JSON.stringify(this.displayColumns))
|
||||||
const final_properties = this.properties.concat(this.removed_properties).filter((field) => {
|
this.form.properties = this.properties.concat(this.removed_properties).filter((field) => {
|
||||||
return this.displayColumns[field.id] === true
|
return this.displayColumns[field.id] === true
|
||||||
})
|
})
|
||||||
this.$set(this.form, 'properties', final_properties)
|
|
||||||
},
|
},
|
||||||
onDeleteRecord() {
|
onDeleteRecord () {
|
||||||
this.fullyLoaded = false
|
this.fullyLoaded = false
|
||||||
this.tableData = []
|
this.tableData = []
|
||||||
this.getSubmissionsData()
|
this.getSubmissionsData()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="showSidebar"
|
<div v-if="showSidebar"
|
||||||
class="absolute shadow-lg shadow-blue-800/30 top-0 h-[calc(100vh-45px)] right-0 lg:shadow-none lg:relative bg-white w-full md:w-1/2 lg:w-2/5 border-l overflow-y-scroll md:max-w-[20rem] flex-shrink-0">
|
class="absolute shadow-lg shadow-blue-800/30 top-0 h-[calc(100vh-45px)] right-0 lg:shadow-none lg:relative bg-white w-full md:w-1/2 lg:w-2/5 border-l overflow-y-scroll md:max-w-[20rem] flex-shrink-0"
|
||||||
|
>
|
||||||
<div class="p-4 border-b sticky top-0 z-10 bg-white">
|
<div class="p-4 border-b sticky top-0 z-10 bg-white">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<button class="text-gray-500 hover:text-gray-900 cursor-pointer" @click.prevent="closeSidebar">
|
<button class="text-gray-500 hover:text-gray-900 cursor-pointer" @click.prevent="closeSidebar">
|
||||||
<svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
<path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
||||||
stroke-linejoin="round"/>
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div class="font-semibold inline ml-2 truncate flex-grow truncate">
|
<div class="font-semibold inline ml-2 truncate flex-grow truncate">
|
||||||
|
@ -18,7 +19,9 @@
|
||||||
|
|
||||||
<div class="py-2 px-4">
|
<div class="py-2 px-4">
|
||||||
<div>
|
<div>
|
||||||
<p class="text-gray-500 uppercase text-xs font-semibold mb-2">Input Blocks</p>
|
<p class="text-gray-500 uppercase text-xs font-semibold mb-2">
|
||||||
|
Input Blocks
|
||||||
|
</p>
|
||||||
<div class="grid grid-cols-2 gap-2">
|
<div class="grid grid-cols-2 gap-2">
|
||||||
<div v-for="(block, i) in inputBlocks" :key="block.name"
|
<div v-for="(block, i) in inputBlocks" :key="block.name"
|
||||||
class="bg-gray-50 border hover:bg-gray-100 dark:bg-gray-900 rounded-md dark:hover:bg-gray-800 py-2 flex flex-col"
|
class="bg-gray-50 border hover:bg-gray-100 dark:bg-gray-900 rounded-md dark:hover:bg-gray-800 py-2 flex flex-col"
|
||||||
|
@ -26,14 +29,19 @@
|
||||||
>
|
>
|
||||||
<div class="mx-auto">
|
<div class="mx-auto">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-gray-500" fill="none" viewBox="0 0 24 24"
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-gray-500" fill="none" viewBox="0 0 24 24"
|
||||||
stroke="currentColor" stroke-width="2" v-html="block.icon"></svg>
|
stroke="currentColor" stroke-width="2" v-html="block.icon"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p class="w-full text-xs text-gray-500 uppercase text-center font-semibold mt-1">{{ block.title }}</p>
|
<p class="w-full text-xs text-gray-500 uppercase text-center font-semibold mt-1">
|
||||||
|
{{ block.title }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-t mt-6">
|
<div class="border-t mt-6">
|
||||||
<p class="text-gray-500 uppercase text-xs font-semibold mb-2 mt-6">Layout Blocks</p>
|
<p class="text-gray-500 uppercase text-xs font-semibold mb-2 mt-6">
|
||||||
|
Layout Blocks
|
||||||
|
</p>
|
||||||
<div class="grid grid-cols-2 gap-2">
|
<div class="grid grid-cols-2 gap-2">
|
||||||
<div v-for="(block, i) in layoutBlocks" :key="block.name"
|
<div v-for="(block, i) in layoutBlocks" :key="block.name"
|
||||||
class="bg-gray-50 border hover:bg-gray-100 dark:bg-gray-900 rounded-md dark:hover:bg-gray-800 py-2 flex flex-col"
|
class="bg-gray-50 border hover:bg-gray-100 dark:bg-gray-900 rounded-md dark:hover:bg-gray-800 py-2 flex flex-col"
|
||||||
|
@ -41,9 +49,12 @@
|
||||||
>
|
>
|
||||||
<div class="mx-auto">
|
<div class="mx-auto">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-gray-500" fill="none" viewBox="0 0 24 24"
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-gray-500" fill="none" viewBox="0 0 24 24"
|
||||||
stroke="currentColor" stroke-width="2" v-html="block.icon"></svg>
|
stroke="currentColor" stroke-width="2" v-html="block.icon"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p class="w-full text-xs text-gray-500 uppercase text-center font-semibold mt-1">{{ block.title }}</p>
|
<p class="w-full text-xs text-gray-500 uppercase text-center font-semibold mt-1">
|
||||||
|
{{ block.title }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -52,7 +63,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {mapState} from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import Form from 'vform'
|
import Form from 'vform'
|
||||||
import clonedeep from 'clone-deep'
|
import clonedeep from 'clone-deep'
|
||||||
|
|
||||||
|
@ -60,91 +71,91 @@ export default {
|
||||||
name: 'AddFormBlockSidebar',
|
name: 'AddFormBlockSidebar',
|
||||||
components: {},
|
components: {},
|
||||||
props: {},
|
props: {},
|
||||||
data() {
|
data () {
|
||||||
return {
|
return {
|
||||||
blockForm: null,
|
blockForm: null,
|
||||||
inputBlocks: [
|
inputBlocks: [
|
||||||
{
|
{
|
||||||
name: 'text',
|
name: 'text',
|
||||||
title: 'Text Input',
|
title: 'Text Input',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h7"/>',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h7"/>'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'date',
|
name: 'date',
|
||||||
title: 'Date Input',
|
title: 'Date Input',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'url',
|
name: 'url',
|
||||||
title: 'URL Input',
|
title: 'URL Input',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/>',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/>'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'phone_number',
|
name: 'phone_number',
|
||||||
title: 'Phone Input',
|
title: 'Phone Input',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"/>',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"/>'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'email',
|
name: 'email',
|
||||||
title: 'Email Input',
|
title: 'Email Input',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M16 12a4 4 0 10-8 0 4 4 0 008 0zm0 0v1.5a2.5 2.5 0 005 0V12a9 9 0 10-9 9m4.5-1.206a8.959 8.959 0 01-4.5 1.207"/>',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M16 12a4 4 0 10-8 0 4 4 0 008 0zm0 0v1.5a2.5 2.5 0 005 0V12a9 9 0 10-9 9m4.5-1.206a8.959 8.959 0 01-4.5 1.207"/>'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'checkbox',
|
name: 'checkbox',
|
||||||
title: 'Checkbox Input',
|
title: 'Checkbox Input',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'select',
|
name: 'select',
|
||||||
title: 'Select Input',
|
title: 'Select Input',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M8 9l4-4 4 4m0 6l-4 4-4-4"/>',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M8 9l4-4 4 4m0 6l-4 4-4-4"/>'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'multi_select',
|
name: 'multi_select',
|
||||||
title: 'Multi-select Input',
|
title: 'Multi-select Input',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M8 9l4-4 4 4m0 6l-4 4-4-4"/>',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M8 9l4-4 4 4m0 6l-4 4-4-4"/>'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'number',
|
name: 'number',
|
||||||
title: 'Number Input',
|
title: 'Number Input',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M7 20l4-16m2 16l4-16M6 9h14M4 15h14"/>',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M7 20l4-16m2 16l4-16M6 9h14M4 15h14"/>'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'files',
|
name: 'files',
|
||||||
title: 'File Input',
|
title: 'File Input',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'signature',
|
name: 'signature',
|
||||||
title: 'Signature Input',
|
title: 'Signature Input',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125" />',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125" />'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
layoutBlocks: [
|
layoutBlocks: [
|
||||||
{
|
{
|
||||||
name: 'nf-text',
|
name: 'nf-text',
|
||||||
title: 'Text Block',
|
title: 'Text Block',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h8m-8 6h16" />',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h8m-8 6h16" />'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'nf-page-break',
|
name: 'nf-page-break',
|
||||||
title: 'Page-break Block',
|
title: 'Page-break Block',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M9 13h6m-3-3v6m5 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M9 13h6m-3-3v6m5 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'nf-divider',
|
name: 'nf-divider',
|
||||||
title: 'Divider Block',
|
title: 'Divider Block',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M20 12H4" />',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M20 12H4" />'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'nf-image',
|
name: 'nf-image',
|
||||||
title: 'Image Block',
|
title: 'Image Block',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'nf-code',
|
name: 'nf-code',
|
||||||
title: 'Code Block',
|
title: 'Code Block',
|
||||||
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5" />',
|
icon: '<path stroke-linecap="round" stroke-linejoin="round" d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5" />'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -156,80 +167,80 @@ export default {
|
||||||
showAddFieldSidebar: state => state['open/working_form'].showAddFieldSidebar
|
showAddFieldSidebar: state => state['open/working_form'].showAddFieldSidebar
|
||||||
}),
|
}),
|
||||||
form: {
|
form: {
|
||||||
get() {
|
get () {
|
||||||
return this.$store.state['open/working_form'].content
|
return this.$store.state['open/working_form'].content
|
||||||
},
|
},
|
||||||
/* We add a setter */
|
/* We add a setter */
|
||||||
set(value) {
|
set (value) {
|
||||||
this.$store.commit('open/working_form/set', value)
|
this.$store.commit('open/working_form/set', value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
showSidebar() {
|
showSidebar () {
|
||||||
return (this.form && this.showAddFieldSidebar) ?? false
|
return (this.form && this.showAddFieldSidebar) ?? false
|
||||||
},
|
},
|
||||||
|
|
||||||
defaultBlockNames() {
|
defaultBlockNames () {
|
||||||
return {
|
return {
|
||||||
'text': 'Your name',
|
text: 'Your name',
|
||||||
'date': 'Date',
|
date: 'Date',
|
||||||
'url': 'Link',
|
url: 'Link',
|
||||||
'phone_number': 'Phone Number',
|
phone_number: 'Phone Number',
|
||||||
'number': 'Number',
|
number: 'Number',
|
||||||
'email': 'Email',
|
email: 'Email',
|
||||||
'checkbox': 'Checkbox',
|
checkbox: 'Checkbox',
|
||||||
'select': 'Select',
|
select: 'Select',
|
||||||
'multi_select': 'Multi Select',
|
multi_select: 'Multi Select',
|
||||||
'files': 'Files',
|
files: 'Files',
|
||||||
'signature': 'Signature',
|
signature: 'Signature',
|
||||||
'nf-text': 'Text Block',
|
'nf-text': 'Text Block',
|
||||||
'nf-page-break': 'Page Break',
|
'nf-page-break': 'Page Break',
|
||||||
'nf-divider': 'Divider',
|
'nf-divider': 'Divider',
|
||||||
'nf-image': 'Image',
|
'nf-image': 'Image',
|
||||||
'nf-code': 'Code Block',
|
'nf-code': 'Code Block'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {},
|
watch: {},
|
||||||
|
|
||||||
mounted() {
|
mounted () {
|
||||||
this.reset()
|
this.reset()
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
closeSidebar() {
|
closeSidebar () {
|
||||||
this.$store.commit('open/working_form/closeAddFieldSidebar')
|
this.$store.commit('open/working_form/closeAddFieldSidebar')
|
||||||
},
|
},
|
||||||
reset() {
|
reset () {
|
||||||
this.blockForm = new Form({
|
this.blockForm = new Form({
|
||||||
type: null,
|
type: null,
|
||||||
name: null
|
name: null
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
addBlock(type) {
|
addBlock (type) {
|
||||||
this.blockForm.type = type
|
this.blockForm.type = type
|
||||||
this.blockForm.name = this.defaultBlockNames[type]
|
this.blockForm.name = this.defaultBlockNames[type]
|
||||||
const newBlock = this.prefillDefault(this.blockForm.data())
|
const newBlock = this.prefillDefault(this.blockForm.data())
|
||||||
newBlock.id = this.generateUUID()
|
newBlock.id = this.generateUUID()
|
||||||
newBlock.hidden = false
|
newBlock.hidden = false
|
||||||
if (['select', 'multi_select'].includes(this.blockForm.type)) {
|
if (['select', 'multi_select'].includes(this.blockForm.type)) {
|
||||||
newBlock[this.blockForm.type] = {'options': []}
|
newBlock[this.blockForm.type] = { options: [] }
|
||||||
}
|
}
|
||||||
newBlock.help_position = 'below_input'
|
newBlock.help_position = 'below_input'
|
||||||
if(this.selectedFieldIndex === null || this.selectedFieldIndex === undefined){
|
if (this.selectedFieldIndex === null || this.selectedFieldIndex === undefined) {
|
||||||
const newFields = clonedeep(this.form.properties)
|
const newFields = clonedeep(this.form.properties)
|
||||||
newFields.push(newBlock)
|
newFields.push(newBlock)
|
||||||
this.$set(this.form, 'properties', newFields)
|
this.form.properties = newFields
|
||||||
this.$store.commit('open/working_form/openSettingsForField', this.form.properties.length-1)
|
this.$store.commit('open/working_form/openSettingsForField', this.form.properties.length - 1)
|
||||||
} else {
|
} else {
|
||||||
const newFields = clonedeep(this.form.properties)
|
const newFields = clonedeep(this.form.properties)
|
||||||
newFields.splice(this.selectedFieldIndex+1, 0, newBlock)
|
newFields.splice(this.selectedFieldIndex + 1, 0, newBlock)
|
||||||
this.$set(this.form, 'properties', newFields)
|
this.form.properties = newFields
|
||||||
this.$store.commit('open/working_form/openSettingsForField', this.selectedFieldIndex+1)
|
this.$store.commit('open/working_form/openSettingsForField', this.selectedFieldIndex + 1)
|
||||||
}
|
}
|
||||||
this.reset()
|
this.reset()
|
||||||
},
|
},
|
||||||
generateUUID() {
|
generateUUID () {
|
||||||
let d = new Date().getTime()// Timestamp
|
let d = new Date().getTime()// Timestamp
|
||||||
let d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now() * 1000)) || 0// Time in microseconds since page-load or 0 if unsupported
|
let d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now() * 1000)) || 0// Time in microseconds since page-load or 0 if unsupported
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||||
|
@ -244,7 +255,7 @@ export default {
|
||||||
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16)
|
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
prefillDefault(data) {
|
prefillDefault (data) {
|
||||||
if (data.type === 'nf-text') {
|
if (data.type === 'nf-text') {
|
||||||
data.content = '<p>This is a text block.</p>'
|
data.content = '<p>This is a text block.</p>'
|
||||||
} else if (data.type === 'nf-page-break') {
|
} else if (data.type === 'nf-page-break') {
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<collapse class="p-4 w-full border-b" v-model="isCollapseOpen">
|
<collapse v-model="isCollapseOpen" class="p-4 w-full border-b">
|
||||||
<template #title>
|
<template #title>
|
||||||
<h3 class="font-semibold text-lg relative">
|
<h3 class="font-semibold text-lg relative">
|
||||||
<svg
|
<svg
|
||||||
class="h-5 w-5 inline mr-2 -mt-0.5 transition-colors" :class="{'text-blue-600':isCollapseOpen, 'text-gray-500':!isCollapseOpen}"
|
class="h-5 w-5 inline mr-2 -mt-0.5 transition-colors" :class="{'text-blue-600':isCollapseOpen, 'text-gray-500':!isCollapseOpen}"
|
||||||
viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
d="M4.83333 6.08333H9M4.83333 9H11.5M4.83333 14V15.9463C4.83333 16.3903 4.83333 16.6123 4.92436 16.7263C5.00352 16.8255 5.12356 16.8832 5.25045 16.8831C5.39636 16.8829 5.56973 16.7442 5.91646 16.4668L7.90434 14.8765C8.31043 14.5517 8.51347 14.3892 8.73957 14.2737C8.94017 14.1712 9.15369 14.0963 9.37435 14.051C9.62306 14 9.88308 14 10.4031 14H12.5C13.9001 14 14.6002 14 15.135 13.7275C15.6054 13.4878 15.9878 13.1054 16.2275 12.635C16.5 12.1002 16.5 11.4001 16.5 10V5.5C16.5 4.09987 16.5 3.3998 16.2275 2.86502C15.9878 2.39462 15.6054 2.01217 15.135 1.77248C14.6002 1.5 13.9001 1.5 12.5 1.5H5.5C4.09987 1.5 3.3998 1.5 2.86502 1.77248C2.39462 2.01217 2.01217 2.39462 1.77248 2.86502C1.5 3.3998 1.5 4.09987 1.5 5.5V10.6667C1.5 11.4416 1.5 11.8291 1.58519 12.147C1.81635 13.0098 2.49022 13.6836 3.35295 13.9148C3.67087 14 4.05836 14 4.83333 14Z"
|
d="M4.83333 6.08333H9M4.83333 9H11.5M4.83333 14V15.9463C4.83333 16.3903 4.83333 16.6123 4.92436 16.7263C5.00352 16.8255 5.12356 16.8832 5.25045 16.8831C5.39636 16.8829 5.56973 16.7442 5.91646 16.4668L7.90434 14.8765C8.31043 14.5517 8.51347 14.3892 8.73957 14.2737C8.94017 14.1712 9.15369 14.0963 9.37435 14.051C9.62306 14 9.88308 14 10.4031 14H12.5C13.9001 14 14.6002 14 15.135 13.7275C15.6054 13.4878 15.9878 13.1054 16.2275 12.635C16.5 12.1002 16.5 11.4001 16.5 10V5.5C16.5 4.09987 16.5 3.3998 16.2275 2.86502C15.9878 2.39462 15.6054 2.01217 15.135 1.77248C14.6002 1.5 13.9001 1.5 12.5 1.5H5.5C4.09987 1.5 3.3998 1.5 2.86502 1.77248C2.39462 2.01217 2.01217 2.39462 1.77248 2.86502C1.5 3.3998 1.5 4.09987 1.5 5.5V10.6667C1.5 11.4416 1.5 11.8291 1.58519 12.147C1.81635 13.0098 2.49022 13.6836 3.35295 13.9148C3.67087 14 4.05836 14 4.83333 14Z"
|
||||||
stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round"/>
|
stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
About Submissions
|
About Submissions
|
||||||
|
@ -43,13 +45,13 @@
|
||||||
<template #selected="{option,optionName}">
|
<template #selected="{option,optionName}">
|
||||||
<div class="flex items-center truncate mr-6">
|
<div class="flex items-center truncate mr-6">
|
||||||
{{ optionName }}
|
{{ optionName }}
|
||||||
<pro-tag v-if="option === 'update'" class="ml-2"/>
|
<pro-tag v-if="option === 'update'" class="ml-2" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #option="{option, selected}">
|
<template #option="{option, selected}">
|
||||||
<span class="flex hover:text-white">
|
<span class="flex hover:text-white">
|
||||||
<p class="flex-grow hover:text-white">
|
<p class="flex-grow hover:text-white">
|
||||||
{{ option.name }} <template v-if="option.value === 'update'"><pro-tag/></template>
|
{{ option.name }} <template v-if="option.value === 'update'"><pro-tag /></template>
|
||||||
</p>
|
</p>
|
||||||
<span v-if="selected" class="absolute inset-y-0 right-0 flex items-center pr-4 dark:text-white">
|
<span v-if="selected" class="absolute inset-y-0 right-0 flex items-center pr-4 dark:text-white">
|
||||||
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
@ -73,7 +75,8 @@
|
||||||
<small>If the submission has the same value(s) as a previous one for the selected
|
<small>If the submission has the same value(s) as a previous one for the selected
|
||||||
column(s), we will update it, instead of creating a new one.
|
column(s), we will update it, instead of creating a new one.
|
||||||
<a href="#"
|
<a href="#"
|
||||||
@click.prevent="$crisp.push(['do', 'helpdesk:article:open', ['en', 'how-to-update-a-page-on-form-submission-1t1jwmn']])">More
|
@click.prevent="$crisp.push(['do', 'helpdesk:article:open', ['en', 'how-to-update-a-page-on-form-submission-1t1jwmn']])"
|
||||||
|
>More
|
||||||
info here.</a>
|
info here.</a>
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -89,13 +92,13 @@
|
||||||
<template #selected="{option,optionName}">
|
<template #selected="{option,optionName}">
|
||||||
<div class="flex items-center truncate mr-6">
|
<div class="flex items-center truncate mr-6">
|
||||||
{{ optionName }}
|
{{ optionName }}
|
||||||
<pro-tag v-if="option === 'redirect'" class="ml-2"/>
|
<pro-tag v-if="option === 'redirect'" class="ml-2" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #option="{option, selected}">
|
<template #option="{option, selected}">
|
||||||
<span class="flex hover:text-white">
|
<span class="flex hover:text-white">
|
||||||
<p class="flex-grow hover:text-white">
|
<p class="flex-grow hover:text-white">
|
||||||
{{ option.name }} <template v-if="option.value === 'redirect'"><pro-tag/></template>
|
{{ option.name }} <template v-if="option.value === 'redirect'"><pro-tag /></template>
|
||||||
</p>
|
</p>
|
||||||
<span v-if="selected" class="absolute inset-y-0 right-0 flex items-center pr-4">
|
<span v-if="selected" class="absolute inset-y-0 right-0 flex items-center pr-4">
|
||||||
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
@ -163,22 +166,22 @@ import ProTag from '../../../../common/ProTag.vue'
|
||||||
import VTransition from '../../../../common/transitions/VTransition.vue'
|
import VTransition from '../../../../common/transitions/VTransition.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {Collapse, ProTag, VTransition},
|
components: { Collapse, ProTag, VTransition },
|
||||||
props: {},
|
props: {},
|
||||||
data() {
|
data () {
|
||||||
return {
|
return {
|
||||||
submissionOptions: {},
|
submissionOptions: {},
|
||||||
isCollapseOpen: true,
|
isCollapseOpen: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
form: {
|
form: {
|
||||||
get() {
|
get () {
|
||||||
return this.$store.state['open/working_form'].content
|
return this.$store.state['open/working_form'].content
|
||||||
},
|
},
|
||||||
/* We add a setter */
|
/* We add a setter */
|
||||||
set(value) {
|
set (value) {
|
||||||
this.$store.commit('open/working_form/set', value)
|
this.$store.commit('open/working_form/set', value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -186,10 +189,10 @@ export default {
|
||||||
* Used for the update record on submission. Lists all visible fields on which you can filter records to update
|
* Used for the update record on submission. Lists all visible fields on which you can filter records to update
|
||||||
* on submission instead of creating
|
* on submission instead of creating
|
||||||
*/
|
*/
|
||||||
filterableFields() {
|
filterableFields () {
|
||||||
if (this.submissionOptions.databaseAction !== 'update') return []
|
if (this.submissionOptions.databaseAction !== 'update') return []
|
||||||
return this.form.properties.filter((field) => {
|
return this.form.properties.filter((field) => {
|
||||||
return !field.hidden && !['files','signature','multi_select'].includes(field.type)
|
return !field.hidden && !['files', 'signature', 'multi_select'].includes(field.type)
|
||||||
}).map((field) => {
|
}).map((field) => {
|
||||||
return {
|
return {
|
||||||
name: field.name,
|
name: field.name,
|
||||||
|
@ -201,7 +204,7 @@ export default {
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
form: {
|
form: {
|
||||||
handler() {
|
handler () {
|
||||||
if (this.form) {
|
if (this.form) {
|
||||||
this.submissionOptions = {
|
this.submissionOptions = {
|
||||||
submissionMode: this.form.redirect_url ? 'redirect' : 'default',
|
submissionMode: this.form.redirect_url ? 'redirect' : 'default',
|
||||||
|
@ -215,14 +218,14 @@ export default {
|
||||||
deep: true,
|
deep: true,
|
||||||
handler: function (val) {
|
handler: function (val) {
|
||||||
if (val.submissionMode === 'default') {
|
if (val.submissionMode === 'default') {
|
||||||
this.$set(this.form, 'redirect_url', null)
|
this.form.redirect_url = null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val.databaseAction === 'create') {
|
if (val.databaseAction === 'create') {
|
||||||
this.$set(this.form, 'database_fields_update', null)
|
this.form.database_fields_update = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<collapse class="p-4 w-full border-b" v-model="isCollapseOpen">
|
<collapse v-model="isCollapseOpen" class="p-4 w-full border-b">
|
||||||
<template #title>
|
<template #title>
|
||||||
<h3 class="font-semibold text-lg">
|
<h3 class="font-semibold text-lg">
|
||||||
<svg class="h-5 w-5 inline mr-2 -mt-1 transition-colors" :class="{'text-blue-600':isCollapseOpen, 'text-gray-500':!isCollapseOpen}" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="h-5 w-5 inline mr-2 -mt-1 transition-colors" :class="{'text-blue-600':isCollapseOpen, 'text-gray-500':!isCollapseOpen}" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M1.66667 9.99984C1.66667 14.6022 5.39763 18.3332 10 18.3332C11.3807 18.3332 12.5 17.2139 12.5 15.8332V15.4165C12.5 15.0295 12.5 14.836 12.5214 14.6735C12.6691 13.5517 13.5519 12.6689 14.6737 12.5212C14.8361 12.4998 15.0297 12.4998 15.4167 12.4998H15.8333C17.214 12.4998 18.3333 11.3805 18.3333 9.99984C18.3333 5.39746 14.6024 1.6665 10 1.6665C5.39763 1.6665 1.66667 5.39746 1.66667 9.99984Z" stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M1.66667 9.99984C1.66667 14.6022 5.39763 18.3332 10 18.3332C11.3807 18.3332 12.5 17.2139 12.5 15.8332V15.4165C12.5 15.0295 12.5 14.836 12.5214 14.6735C12.6691 13.5517 13.5519 12.6689 14.6737 12.5212C14.8361 12.4998 15.0297 12.4998 15.4167 12.4998H15.8333C17.214 12.4998 18.3333 11.3805 18.3333 9.99984C18.3333 5.39746 14.6024 1.6665 10 1.6665C5.39763 1.6665 1.66667 5.39746 1.66667 9.99984Z" stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
<path d="M5.83333 10.8332C6.29357 10.8332 6.66667 10.4601 6.66667 9.99984C6.66667 9.5396 6.29357 9.1665 5.83333 9.1665C5.3731 9.1665 5 9.5396 5 9.99984C5 10.4601 5.3731 10.8332 5.83333 10.8332Z" stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M5.83333 10.8332C6.29357 10.8332 6.66667 10.4601 6.66667 9.99984C6.66667 9.5396 6.29357 9.1665 5.83333 9.1665C5.3731 9.1665 5 9.5396 5 9.99984C5 10.4601 5.3731 10.8332 5.83333 10.8332Z" stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
<path d="M13.3333 7.49984C13.7936 7.49984 14.1667 7.12674 14.1667 6.6665C14.1667 6.20627 13.7936 5.83317 13.3333 5.83317C12.8731 5.83317 12.5 6.20627 12.5 6.6665C12.5 7.12674 12.8731 7.49984 13.3333 7.49984Z" stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M13.3333 7.49984C13.7936 7.49984 14.1667 7.12674 14.1667 6.6665C14.1667 6.20627 13.7936 5.83317 13.3333 5.83317C12.8731 5.83317 12.5 6.20627 12.5 6.6665C12.5 7.12674 12.8731 7.49984 13.3333 7.49984Z" stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
<path d="M8.33333 6.6665C8.79357 6.6665 9.16667 6.29341 9.16667 5.83317C9.16667 5.37293 8.79357 4.99984 8.33333 4.99984C7.8731 4.99984 7.5 5.37293 7.5 5.83317C7.5 6.29341 7.8731 6.6665 8.33333 6.6665Z" stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M8.33333 6.6665C8.79357 6.6665 9.16667 6.29341 9.16667 5.83317C9.16667 5.37293 8.79357 4.99984 8.33333 4.99984C7.8731 4.99984 7.5 5.37293 7.5 5.83317C7.5 6.29341 7.8731 6.6665 8.33333 6.6665Z" stroke="currentColor" stroke-width="1.67" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
Customization
|
Customization
|
||||||
|
@ -113,21 +113,21 @@ export default {
|
||||||
|
|
||||||
watch: {},
|
watch: {},
|
||||||
|
|
||||||
mounted() {
|
mounted () {
|
||||||
this.isMounted = true
|
this.isMounted = true
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onChangeConfettiOnSubmission(val) {
|
onChangeConfettiOnSubmission (val) {
|
||||||
this.$set(this.form, 'confetti_on_submission', val)
|
this.form.confetti_on_submission = val
|
||||||
if(this.isMounted && val){
|
if (this.isMounted && val) {
|
||||||
this.playConfetti()
|
this.playConfetti()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openChat () {
|
openChat () {
|
||||||
window.$crisp.push(['do', 'chat:show'])
|
window.$crisp.push(['do', 'chat:show'])
|
||||||
window.$crisp.push(['do', 'chat:open'])
|
window.$crisp.push(['do', 'chat:open'])
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -32,8 +32,8 @@
|
||||||
label="Send submission confirmation" :help="emailSubmissionConfirmationHelp"
|
label="Send submission confirmation" :help="emailSubmissionConfirmationHelp"
|
||||||
/>
|
/>
|
||||||
<template v-if="form.send_submission_confirmation">
|
<template v-if="form.send_submission_confirmation">
|
||||||
<text-input name="confirmation_reply_to"
|
<text-input v-model="form.notification_settings.confirmation_reply_to"
|
||||||
v-model="form.notification_settings.confirmation_reply_to" class="mt-4"
|
name="confirmation_reply_to" class="mt-4"
|
||||||
label="Confirmation Reply To" help="help"
|
label="Confirmation Reply To" help="help"
|
||||||
>
|
>
|
||||||
<template #help>
|
<template #help>
|
||||||
|
@ -102,7 +102,7 @@ export default {
|
||||||
watch: {
|
watch: {
|
||||||
emailSubmissionConfirmationField (val) {
|
emailSubmissionConfirmationField (val) {
|
||||||
if (val === null) {
|
if (val === null) {
|
||||||
this.$set(this.form, 'send_submission_confirmation', false)
|
this.form.send_submission_confirmation = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<div>
|
<div>
|
||||||
<v-button color="light-gray" size="small" @click="showCopyFormModal=true">
|
<v-button color="light-gray" size="small" @click="showCopyFormModal=true">
|
||||||
<svg class="h-4 w-4 text-blue-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="h-4 w-4 text-blue-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M5 15H4C3.46957 15 2.96086 14.7893 2.58579 14.4142C2.21071 14.0391 2 13.5304 2 13V4C2 3.46957 2.21071 2.96086 2.58579 2.58579C2.96086 2.21071 3.46957 2 4 2H13C13.5304 2 14.0391 2.21071 14.4142 2.58579C14.7893 2.96086 15 3.46957 15 4V5M11 9H20C21.1046 9 22 9.89543 22 11V20C22 21.1046 21.1046 22 20 22H11C9.89543 22 9 21.1046 9 20V11C9 9.89543 9.89543 9 11 9Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M5 15H4C3.46957 15 2.96086 14.7893 2.58579 14.4142C2.21071 14.0391 2 13.5304 2 13V4C2 3.46957 2.21071 2.96086 2.58579 2.58579C2.96086 2.21071 3.46957 2 4 2H13C13.5304 2 14.0391 2.21071 14.4142 2.58579C14.7893 2.96086 15 3.46957 15 4V5M11 9H20C21.1046 9 22 9.89543 22 11V20C22 21.1046 21.1046 22 20 22H11C9.89543 22 9 21.1046 9 20V11C9 9.89543 9.89543 9 11 9Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
</svg>
|
</svg>
|
||||||
Copy from
|
Copy from
|
||||||
</v-button>
|
</v-button>
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
<div>
|
<div>
|
||||||
<v-button color="light-gray" shade="light" size="small" class="ml-1" @click="clearAll">
|
<v-button color="light-gray" shade="light" size="small" class="ml-1" @click="clearAll">
|
||||||
<svg class="text-red-600 h-4 w-4 inline -mt-1 mr-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="text-red-600 h-4 w-4 inline -mt-1 mr-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M18 9L12 15M12 9L18 15M21 4H8L1 12L8 20H21C21.5304 20 22.0391 19.7893 22.4142 19.4142C22.7893 19.0391 23 18.5304 23 18V6C23 5.46957 22.7893 4.96086 22.4142 4.58579C22.0391 4.21071 21.5304 4 21 4Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M18 9L12 15M12 9L18 15M21 4H8L1 12L8 20H21C21.5304 20 22.0391 19.7893 22.4142 19.4142C22.7893 19.0391 23 18.5304 23 18V6C23 5.46957 22.7893 4.96086 22.4142 4.58579C22.0391 4.21071 21.5304 4 21 4Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
Clear All
|
Clear All
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
<h5 class="font-semibold mt-3">
|
<h5 class="font-semibold mt-3">
|
||||||
1. Conditions
|
1. Conditions
|
||||||
</h5>
|
</h5>
|
||||||
<condition-editor ref="filter-editor" v-model="logic.conditions" class="mt-1 border-t border rounded-md" :form="form"/>
|
<condition-editor ref="filter-editor" v-model="logic.conditions" class="mt-1 border-t border rounded-md" :form="form" />
|
||||||
|
|
||||||
<h5 class="font-semibold mt-3">
|
<h5 class="font-semibold mt-3">
|
||||||
2. Actions
|
2. Actions
|
||||||
|
@ -75,7 +75,7 @@ import clonedeep from 'clone-deep'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'FormBlockLogicEditor',
|
name: 'FormBlockLogicEditor',
|
||||||
components: {SelectInput, Modal, ProTag, ConditionEditor},
|
components: { SelectInput, Modal, ProTag, ConditionEditor },
|
||||||
props: {
|
props: {
|
||||||
field: {
|
field: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -87,7 +87,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data () {
|
||||||
return {
|
return {
|
||||||
resetKey: 0,
|
resetKey: 0,
|
||||||
logic: this.field.logic || {
|
logic: this.field.logic || {
|
||||||
|
@ -95,31 +95,31 @@ export default {
|
||||||
actions: []
|
actions: []
|
||||||
},
|
},
|
||||||
showCopyFormModal: false,
|
showCopyFormModal: false,
|
||||||
copyFrom: null,
|
copyFrom: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
copyFromOptions() {
|
copyFromOptions () {
|
||||||
return this.form.properties.filter((field) => {
|
return this.form.properties.filter((field) => {
|
||||||
return field.id !== this.field.id && field.hasOwnProperty('logic') && field.logic !== null && field.logic !== {}
|
return field.id !== this.field.id && field.hasOwnProperty('logic') && field.logic !== null && field.logic !== {}
|
||||||
}).map((field) => {
|
}).map((field) => {
|
||||||
return {name: field.name, value: field.id}
|
return { name: field.name, value: field.id }
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
actionOptions() {
|
actionOptions () {
|
||||||
if (['nf-text', 'nf-code', 'nf-page-break', 'nf-divider', 'nf-image'].includes(this.field.type)) {
|
if (['nf-text', 'nf-code', 'nf-page-break', 'nf-divider', 'nf-image'].includes(this.field.type)) {
|
||||||
if (this.field.hidden) {
|
if (this.field.hidden) {
|
||||||
return [{ name: 'Show Block', value: 'show-block' }]
|
return [{ name: 'Show Block', value: 'show-block' }]
|
||||||
}else{
|
} else {
|
||||||
return [{ name: 'Hide Block', value: 'hide-block' }]
|
return [{ name: 'Hide Block', value: 'hide-block' }]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.field.hidden) {
|
if (this.field.hidden) {
|
||||||
return [
|
return [
|
||||||
{name: 'Show Block', value: 'show-block'},
|
{ name: 'Show Block', value: 'show-block' },
|
||||||
{name: 'Require answer', value: 'require-answer'}
|
{ name: 'Require answer', value: 'require-answer' }
|
||||||
]
|
]
|
||||||
} else if (this.field.disabled) {
|
} else if (this.field.disabled) {
|
||||||
return [
|
return [
|
||||||
|
@ -133,10 +133,10 @@ export default {
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
return [
|
return [
|
||||||
{name: 'Hide Block', value: 'hide-block'},
|
{ name: 'Hide Block', value: 'hide-block' },
|
||||||
{ name: 'Disable Block', value: 'disable-block' },
|
{ name: 'Disable Block', value: 'disable-block' },
|
||||||
(this.field.required
|
(this.field.required
|
||||||
? {name: 'Make it optional', value: 'make-it-optional'}
|
? { name: 'Make it optional', value: 'make-it-optional' }
|
||||||
: {
|
: {
|
||||||
name: 'Require answer',
|
name: 'Require answer',
|
||||||
value: 'require-answer'
|
value: 'require-answer'
|
||||||
|
@ -148,8 +148,8 @@ export default {
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
logic: {
|
logic: {
|
||||||
handler() {
|
handler () {
|
||||||
this.$set(this.field, 'logic', this.logic)
|
this.field.logic = this.logic
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
},
|
},
|
||||||
|
@ -164,46 +164,46 @@ export default {
|
||||||
},
|
},
|
||||||
'field.required': 'cleanConditions',
|
'field.required': 'cleanConditions',
|
||||||
'field.disabled': 'cleanConditions',
|
'field.disabled': 'cleanConditions',
|
||||||
'field.hidden': 'cleanConditions',
|
'field.hidden': 'cleanConditions'
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted () {
|
||||||
if (!this.field.hasOwnProperty('logic')) {
|
if (!this.field.hasOwnProperty('logic')) {
|
||||||
this.$set(this.field, 'logic', this.logic)
|
this.field.logic = this.logic
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
clearAll() {
|
clearAll () {
|
||||||
this.$set(this.logic, 'conditions', null)
|
this.logic.conditions = null
|
||||||
this.$set(this.logic, 'actions', [])
|
this.logic.actions = []
|
||||||
this.refreshActions()
|
this.refreshActions()
|
||||||
},
|
},
|
||||||
onActionInput() {
|
onActionInput () {
|
||||||
if (this.logic.actions.length >= 2) {
|
if (this.logic.actions.length >= 2) {
|
||||||
if (this.logic.actions[1] === 'require-answer' && this.logic.actions[0] === 'hide-block') {
|
if (this.logic.actions[1] === 'require-answer' && this.logic.actions[0] === 'hide-block') {
|
||||||
this.$set(this.logic, 'actions', ['require-answer'])
|
this.logic.actions = ['require-answer']
|
||||||
} else if (this.logic.actions[1] === 'hide-block' && this.logic.actions[0] === 'require-answer') {
|
} else if (this.logic.actions[1] === 'hide-block' && this.logic.actions[0] === 'require-answer') {
|
||||||
this.$set(this.logic, 'actions', ['hide-block'])
|
this.logic.actions = ['hide-block']
|
||||||
}
|
}
|
||||||
this.refreshActions()
|
this.refreshActions()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
cleanConditions() {
|
cleanConditions () {
|
||||||
const availableActions = this.actionOptions.map(function(op){ return op.value });
|
const availableActions = this.actionOptions.map(function (op) { return op.value })
|
||||||
this.$set(this.logic, 'actions', availableActions.filter(value => this.logic.actions.includes(value)))
|
this.logic.actions = availableActions.filter(value => this.logic.actions.includes(value))
|
||||||
this.refreshActions()
|
this.refreshActions()
|
||||||
},
|
},
|
||||||
refreshActions() {
|
refreshActions () {
|
||||||
this.resetKey++
|
this.resetKey++
|
||||||
},
|
},
|
||||||
copyLogic() {
|
copyLogic () {
|
||||||
if (this.copyFrom) {
|
if (this.copyFrom) {
|
||||||
const property = this.form.properties.find((property) => {
|
const property = this.form.properties.find((property) => {
|
||||||
return property.id === this.copyFrom
|
return property.id === this.copyFrom
|
||||||
})
|
})
|
||||||
if (property && property.logic) {
|
if (property && property.logic) {
|
||||||
this.$set(this, 'logic', clonedeep(property.logic))
|
this.logic = clonedeep(property.logic)
|
||||||
this.cleanConditions()
|
this.cleanConditions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<div>
|
<div>
|
||||||
<v-button color="light-gray" size="small" @click="removeBlock">
|
<v-button color="light-gray" size="small" @click="removeBlock">
|
||||||
<svg class="h-4 w-4 text-red-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="h-4 w-4 text-red-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M3 6H5M5 6H21M5 6V20C5 20.5304 5.21071 21.0391 5.58579 21.4142C5.96086 21.7893 6.46957 22 7 22H17C17.5304 22 18.0391 21.7893 18.4142 21.4142C18.7893 21.0391 19 20.5304 19 20V6H5ZM8 6V4C8 3.46957 8.21071 2.96086 8.58579 2.58579C8.96086 2.21071 9.46957 2 10 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4V6M10 11V17M14 11V17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M3 6H5M5 6H21M5 6V20C5 20.5304 5.21071 21.0391 5.58579 21.4142C5.96086 21.7893 6.46957 22 7 22H17C17.5304 22 18.0391 21.7893 18.4142 21.4142C18.7893 21.0391 19 20.5304 19 20V6H5ZM8 6V4C8 3.46957 8.21071 2.96086 8.58579 2.58579C8.96086 2.21071 9.46957 2 10 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4V6M10 11V17M14 11V17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
Remove
|
Remove
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
<div class="ml-1">
|
<div class="ml-1">
|
||||||
<v-button size="small" color="light-gray" @click="duplicateBlock">
|
<v-button size="small" color="light-gray" @click="duplicateBlock">
|
||||||
<svg class="h-4 w-4 text-blue-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="h-4 w-4 text-blue-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M5 15H4C3.46957 15 2.96086 14.7893 2.58579 14.4142C2.21071 14.0391 2 13.5304 2 13V4C2 3.46957 2.21071 2.96086 2.58579 2.58579C2.96086 2.21071 3.46957 2 4 2H13C13.5304 2 14.0391 2.21071 14.4142 2.58579C14.7893 2.96086 15 3.46957 15 4V5M11 9H20C21.1046 9 22 9.89543 22 11V20C22 21.1046 21.1046 22 20 22H11C9.89543 22 9 21.1046 9 20V11C9 9.89543 9.89543 9 11 9Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M5 15H4C3.46957 15 2.96086 14.7893 2.58579 14.4142C2.21071 14.0391 2 13.5304 2 13V4C2 3.46957 2.21071 2.96086 2.58579 2.58579C2.96086 2.21071 3.46957 2 4 2H13C13.5304 2 14.0391 2.21071 14.4142 2.58579C14.7893 2.96086 15 3.46957 15 4V5M11 9H20C21.1046 9 22 9.89543 22 11V20C22 21.1046 21.1046 22 20 22H11C9.89543 22 9 21.1046 9 20V11C9 9.89543 9.89543 9 11 9Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
</svg>
|
</svg>
|
||||||
Duplicate
|
Duplicate
|
||||||
</v-button>
|
</v-button>
|
||||||
|
@ -100,14 +100,15 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="field.type == 'nf-code'" class="-mx-4 sm:-mx-6 p-5 border-b border-t">
|
<div v-else-if="field.type == 'nf-code'" class="-mx-4 sm:-mx-6 p-5 border-b border-t">
|
||||||
<code-input name="content" class="mt-4 h-36" :form="field" label="Content"
|
<code-input name="content" class="mt-4 h-36" :form="field" label="Content"
|
||||||
help="You can add any html code, including iframes" />
|
help="You can add any html code, including iframes"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="-mx-4 sm:-mx-6 p-5 border-b border-t">
|
<div v-else class="-mx-4 sm:-mx-6 p-5 border-b border-t">
|
||||||
<p>No settings found.</p>
|
<p>No settings found.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Logic Block -->
|
<!-- Logic Block -->
|
||||||
<form-block-logic-editor :form="form" :field="field" v-model="form"/>
|
<form-block-logic-editor v-model="form" :form="form" :field="field" />
|
||||||
|
|
||||||
<div class="pt-5 flex justify-end">
|
<div class="pt-5 flex justify-end">
|
||||||
<v-button color="white" @click="close">
|
<v-button color="white" @click="close">
|
||||||
|
@ -123,12 +124,12 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ProTag from '../../../common/ProTag.vue'
|
import ProTag from '../../../common/ProTag.vue'
|
||||||
const FormBlockLogicEditor = () => import('../components/form-logic-components/FormBlockLogicEditor.vue')
|
|
||||||
import CodeInput from '../../../forms/CodeInput.vue'
|
import CodeInput from '../../../forms/CodeInput.vue'
|
||||||
|
const FormBlockLogicEditor = () => import('../components/form-logic-components/FormBlockLogicEditor.vue')
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'FormBlockOptionsModal',
|
name: 'FormBlockOptionsModal',
|
||||||
components: {ProTag, FormBlockLogicEditor, CodeInput},
|
components: { ProTag, FormBlockLogicEditor, CodeInput },
|
||||||
props: {
|
props: {
|
||||||
field: {
|
field: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -143,10 +144,10 @@ export default {
|
||||||
required: false
|
required: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data () {
|
||||||
return {
|
return {
|
||||||
editorToolbarCustom: [
|
editorToolbarCustom: [
|
||||||
['bold', 'italic', 'underline', 'link'],
|
['bold', 'italic', 'underline', 'link']
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -157,7 +158,7 @@ export default {
|
||||||
'field.width': {
|
'field.width': {
|
||||||
handler (val) {
|
handler (val) {
|
||||||
if (val === undefined || val === null) {
|
if (val === undefined || val === null) {
|
||||||
this.$set(this.field, 'width', 'full')
|
this.field.width = 'full'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
|
@ -165,38 +166,38 @@ export default {
|
||||||
'field.align': {
|
'field.align': {
|
||||||
handler (val) {
|
handler (val) {
|
||||||
if (val === undefined || val === null) {
|
if (val === undefined || val === null) {
|
||||||
this.$set(this.field, 'align', 'left')
|
this.field.align = 'left'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted () {
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
close() {
|
close () {
|
||||||
this.$emit('close')
|
this.$emit('close')
|
||||||
},
|
},
|
||||||
removeBlock() {
|
removeBlock () {
|
||||||
this.close()
|
this.close()
|
||||||
this.$emit('remove-block', this.field)
|
this.$emit('remove-block', this.field)
|
||||||
},
|
},
|
||||||
duplicateBlock(){
|
duplicateBlock () {
|
||||||
this.close()
|
this.close()
|
||||||
this.$emit('duplicate-block', this.field)
|
this.$emit('duplicate-block', this.field)
|
||||||
},
|
},
|
||||||
onFieldHiddenChange(val) {
|
onFieldHiddenChange (val) {
|
||||||
this.$set(this.field, 'hidden', val)
|
this.field.hidden = val
|
||||||
if (this.field.hidden) {
|
if (this.field.hidden) {
|
||||||
this.$set(this.field, 'required', false)
|
this.field.required = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldHelpPositionChange (val) {
|
onFieldHelpPositionChange (val) {
|
||||||
if(!val){
|
if (!val) {
|
||||||
this.$set(this.field, 'help_position', 'below_input')
|
this.field.help_position = 'below_input'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="showSidebar"
|
<div v-if="showSidebar"
|
||||||
class="absolute shadow-lg shadow-blue-800/30 top-0 h-[calc(100vh-45px)] right-0 lg:shadow-none lg:relative bg-white w-full md:w-1/2 lg:w-2/5 border-l overflow-y-scroll md:max-w-[20rem] flex-shrink-0 overflow-x-hidden">
|
class="absolute shadow-lg shadow-blue-800/30 top-0 h-[calc(100vh-45px)] right-0 lg:shadow-none lg:relative bg-white w-full md:w-1/2 lg:w-2/5 border-l overflow-y-scroll md:max-w-[20rem] flex-shrink-0 overflow-x-hidden"
|
||||||
|
>
|
||||||
<div class="p-4 border-b sticky top-0 z-10 bg-white">
|
<div class="p-4 border-b sticky top-0 z-10 bg-white">
|
||||||
<button v-if="!field" class="text-gray-500 hover:text-gray-900 cursor-pointer" @click.prevent="closeSidebar">
|
<button v-if="!field" class="text-gray-500 hover:text-gray-900 cursor-pointer" @click.prevent="closeSidebar">
|
||||||
<svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
<path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
||||||
stroke-linejoin="round"/>
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
@ -13,7 +15,8 @@
|
||||||
<button class="text-gray-500 hover:text-gray-900 cursor-pointer" @click.prevent="closeSidebar">
|
<button class="text-gray-500 hover:text-gray-900 cursor-pointer" @click.prevent="closeSidebar">
|
||||||
<svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
<path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
||||||
stroke-linejoin="round"/>
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div class="font-semibold inline ml-2 truncate flex-grow truncate">
|
<div class="font-semibold inline ml-2 truncate flex-grow truncate">
|
||||||
|
@ -22,36 +25,43 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="flex mt-2">
|
<div class="flex mt-2">
|
||||||
<v-button color="light-gray" class="border-r-0 rounded-r-none text-xs hover:bg-red-50" size="small"
|
<v-button color="light-gray" class="border-r-0 rounded-r-none text-xs hover:bg-red-50" size="small"
|
||||||
@click="removeBlock">
|
@click="removeBlock"
|
||||||
|
>
|
||||||
<svg class="h-4 w-4 text-red-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none"
|
<svg class="h-4 w-4 text-red-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
d="M3 6H5M5 6H21M5 6V20C5 20.5304 5.21071 21.0391 5.58579 21.4142C5.96086 21.7893 6.46957 22 7 22H17C17.5304 22 18.0391 21.7893 18.4142 21.4142C18.7893 21.0391 19 20.5304 19 20V6H5ZM8 6V4C8 3.46957 8.21071 2.96086 8.58579 2.58579C8.96086 2.21071 9.46957 2 10 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4V6M10 11V17M14 11V17"
|
d="M3 6H5M5 6H21M5 6V20C5 20.5304 5.21071 21.0391 5.58579 21.4142C5.96086 21.7893 6.46957 22 7 22H17C17.5304 22 18.0391 21.7893 18.4142 21.4142C18.7893 21.0391 19 20.5304 19 20V6H5ZM8 6V4C8 3.46957 8.21071 2.96086 8.58579 2.58579C8.96086 2.21071 9.46957 2 10 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4V6M10 11V17M14 11V17"
|
||||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
Remove
|
Remove
|
||||||
</v-button>
|
</v-button>
|
||||||
<v-button size="small" class="text-xs" :class="{
|
<v-button size="small" class="text-xs" :class="{
|
||||||
'rounded-none border-r-0':!isBlockField && typeCanBeChanged,
|
'rounded-none border-r-0':!isBlockField && typeCanBeChanged,
|
||||||
'rounded-l-none':isBlockField || !typeCanBeChanged
|
'rounded-l-none':isBlockField || !typeCanBeChanged
|
||||||
}" color="light-gray" @click="duplicateBlock">
|
}" color="light-gray" @click="duplicateBlock"
|
||||||
|
>
|
||||||
<svg class="h-4 w-4 text-blue-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none"
|
<svg class="h-4 w-4 text-blue-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
d="M5 15H4C3.46957 15 2.96086 14.7893 2.58579 14.4142C2.21071 14.0391 2 13.5304 2 13V4C2 3.46957 2.21071 2.96086 2.58579 2.58579C2.96086 2.21071 3.46957 2 4 2H13C13.5304 2 14.0391 2.21071 14.4142 2.58579C14.7893 2.96086 15 3.46957 15 4V5M11 9H20C21.1046 9 22 9.89543 22 11V20C22 21.1046 21.1046 22 20 22H11C9.89543 22 9 21.1046 9 20V11C9 9.89543 9.89543 9 11 9Z"
|
d="M5 15H4C3.46957 15 2.96086 14.7893 2.58579 14.4142C2.21071 14.0391 2 13.5304 2 13V4C2 3.46957 2.21071 2.96086 2.58579 2.58579C2.96086 2.21071 3.46957 2 4 2H13C13.5304 2 14.0391 2.21071 14.4142 2.58579C14.7893 2.96086 15 3.46957 15 4V5M11 9H20C21.1046 9 22 9.89543 22 11V20C22 21.1046 21.1046 22 20 22H11C9.89543 22 9 21.1046 9 20V11C9 9.89543 9.89543 9 11 9Z"
|
||||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
Duplicate
|
Duplicate
|
||||||
</v-button>
|
</v-button>
|
||||||
<change-field-type btn-classes="rounded-l-none text-xs" v-if="!isBlockField" :field="field"
|
<change-field-type v-if="!isBlockField" btn-classes="rounded-l-none text-xs" :field="field"
|
||||||
@changeType="onChangeType"/>
|
@changeType="onChangeType"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-if="field">
|
<template v-if="field">
|
||||||
<field-options v-if="!isBlockField" :form="form" :field="field"/>
|
<field-options v-if="!isBlockField" :form="form" :field="field" />
|
||||||
<block-options v-if="isBlockField" :form="form" :field="field"/>
|
<block-options v-if="isBlockField" :form="form" :field="field" />
|
||||||
</template>
|
</template>
|
||||||
<div v-else class="text-center p-10">
|
<div v-else class="text-center p-10">
|
||||||
Click on field's setting icon in your form to modify it
|
Click on field's setting icon in your form to modify it
|
||||||
|
@ -60,17 +70,17 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {mapState} from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import clonedeep from 'clone-deep'
|
import clonedeep from 'clone-deep'
|
||||||
import ChangeFieldType from "./components/ChangeFieldType.vue"
|
import ChangeFieldType from './components/ChangeFieldType.vue'
|
||||||
import FieldOptions from './components/FieldOptions.vue'
|
import FieldOptions from './components/FieldOptions.vue'
|
||||||
import BlockOptions from './components/BlockOptions.vue'
|
import BlockOptions from './components/BlockOptions.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'FormFieldEditSidebar',
|
name: 'FormFieldEditSidebar',
|
||||||
components: {ChangeFieldType, FieldOptions, BlockOptions},
|
components: { ChangeFieldType, FieldOptions, BlockOptions },
|
||||||
props: {},
|
props: {},
|
||||||
data() {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -82,62 +92,62 @@ export default {
|
||||||
showEditFieldSidebar: state => state['open/working_form'].showEditFieldSidebar
|
showEditFieldSidebar: state => state['open/working_form'].showEditFieldSidebar
|
||||||
}),
|
}),
|
||||||
form: {
|
form: {
|
||||||
get() {
|
get () {
|
||||||
return this.$store.state['open/working_form'].content
|
return this.$store.state['open/working_form'].content
|
||||||
},
|
},
|
||||||
/* We add a setter */
|
/* We add a setter */
|
||||||
set(value) {
|
set (value) {
|
||||||
this.$store.commit('open/working_form/set', value)
|
this.$store.commit('open/working_form/set', value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
field() {
|
field () {
|
||||||
return (this.form && this.selectedFieldIndex !== null) ? this.form.properties[this.selectedFieldIndex] : null
|
return (this.form && this.selectedFieldIndex !== null) ? this.form.properties[this.selectedFieldIndex] : null
|
||||||
},
|
},
|
||||||
showSidebar() {
|
showSidebar () {
|
||||||
return (this.form && this.selectedFieldIndex !== null) ? (this.form.properties[this.selectedFieldIndex] && this.showEditFieldSidebar) : false
|
return (this.form && this.selectedFieldIndex !== null) ? (this.form.properties[this.selectedFieldIndex] && this.showEditFieldSidebar) : false
|
||||||
},
|
},
|
||||||
isBlockField() {
|
isBlockField () {
|
||||||
return this.field && this.field.type.startsWith('nf')
|
return this.field && this.field.type.startsWith('nf')
|
||||||
},
|
},
|
||||||
typeCanBeChanged() {
|
typeCanBeChanged () {
|
||||||
return ['text', 'email', 'phone', 'number','select', 'multi_select'].includes(this.field.type)
|
return ['text', 'email', 'phone', 'number', 'select', 'multi_select'].includes(this.field.type)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {},
|
watch: {},
|
||||||
|
|
||||||
created() {
|
created () {
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted () {
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onChangeType(newType) {
|
onChangeType (newType) {
|
||||||
if (['select', 'multi_select'].includes(this.field.type)) {
|
if (['select', 'multi_select'].includes(this.field.type)) {
|
||||||
this.$set(this.field, newType, this.field[this.field.type]) // Set new options with new type
|
this.field[newType] = this.field[this.field.type] // Set new options with new type
|
||||||
this.$delete(this.field, this.field.type) // remove old type options
|
delete this.field[this.field.type] // remove old type options
|
||||||
}
|
}
|
||||||
this.$set(this.field, 'type', newType)
|
this.field.type = newType
|
||||||
},
|
},
|
||||||
removeBlock() {
|
removeBlock () {
|
||||||
const newFields = clonedeep(this.form.properties)
|
const newFields = clonedeep(this.form.properties)
|
||||||
newFields.splice(this.selectedFieldIndex, 1)
|
newFields.splice(this.selectedFieldIndex, 1)
|
||||||
this.$set(this.form, 'properties', newFields)
|
this.form.properties = newFields
|
||||||
this.closeSidebar()
|
this.closeSidebar()
|
||||||
},
|
},
|
||||||
duplicateBlock() {
|
duplicateBlock () {
|
||||||
const newFields = clonedeep(this.form.properties)
|
const newFields = clonedeep(this.form.properties)
|
||||||
const newField = clonedeep(this.form.properties[this.selectedFieldIndex])
|
const newField = clonedeep(this.form.properties[this.selectedFieldIndex])
|
||||||
newField.id = this.generateUUID()
|
newField.id = this.generateUUID()
|
||||||
newFields.push(newField)
|
newFields.push(newField)
|
||||||
this.$set(this.form, 'properties', newFields)
|
this.form.properties = newFields
|
||||||
this.closeSidebar()
|
this.closeSidebar()
|
||||||
},
|
},
|
||||||
closeSidebar() {
|
closeSidebar () {
|
||||||
this.$store.commit('open/working_form/closeEditFieldSidebar')
|
this.$store.commit('open/working_form/closeEditFieldSidebar')
|
||||||
},
|
},
|
||||||
generateUUID() {
|
generateUUID () {
|
||||||
let d = new Date().getTime()// Timestamp
|
let d = new Date().getTime()// Timestamp
|
||||||
let d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now() * 1000)) || 0// Time in microseconds since page-load or 0 if unsupported
|
let d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now() * 1000)) || 0// Time in microseconds since page-load or 0 if unsupported
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||||
|
|
|
@ -9,10 +9,12 @@
|
||||||
<div>
|
<div>
|
||||||
<v-button color="light-gray" size="small" @click="removeBlock">
|
<v-button color="light-gray" size="small" @click="removeBlock">
|
||||||
<svg class="h-4 w-4 text-red-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none"
|
<svg class="h-4 w-4 text-red-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
d="M3 6H5M5 6H21M5 6V20C5 20.5304 5.21071 21.0391 5.58579 21.4142C5.96086 21.7893 6.46957 22 7 22H17C17.5304 22 18.0391 21.7893 18.4142 21.4142C18.7893 21.0391 19 20.5304 19 20V6H5ZM8 6V4C8 3.46957 8.21071 2.96086 8.58579 2.58579C8.96086 2.21071 9.46957 2 10 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4V6M10 11V17M14 11V17"
|
d="M3 6H5M5 6H21M5 6V20C5 20.5304 5.21071 21.0391 5.58579 21.4142C5.96086 21.7893 6.46957 22 7 22H17C17.5304 22 18.0391 21.7893 18.4142 21.4142C18.7893 21.0391 19 20.5304 19 20V6H5ZM8 6V4C8 3.46957 8.21071 2.96086 8.58579 2.58579C8.96086 2.21071 9.46957 2 10 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4V6M10 11V17M14 11V17"
|
||||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
Remove
|
Remove
|
||||||
|
@ -21,15 +23,17 @@
|
||||||
<div class="ml-1">
|
<div class="ml-1">
|
||||||
<v-button size="small" color="light-gray" @click="duplicateBlock">
|
<v-button size="small" color="light-gray" @click="duplicateBlock">
|
||||||
<svg class="h-4 w-4 text-blue-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none"
|
<svg class="h-4 w-4 text-blue-600 inline mr-1 -mt-1" viewBox="0 0 24 24" fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
d="M5 15H4C3.46957 15 2.96086 14.7893 2.58579 14.4142C2.21071 14.0391 2 13.5304 2 13V4C2 3.46957 2.21071 2.96086 2.58579 2.58579C2.96086 2.21071 3.46957 2 4 2H13C13.5304 2 14.0391 2.21071 14.4142 2.58579C14.7893 2.96086 15 3.46957 15 4V5M11 9H20C21.1046 9 22 9.89543 22 11V20C22 21.1046 21.1046 22 20 22H11C9.89543 22 9 21.1046 9 20V11C9 9.89543 9.89543 9 11 9Z"
|
d="M5 15H4C3.46957 15 2.96086 14.7893 2.58579 14.4142C2.21071 14.0391 2 13.5304 2 13V4C2 3.46957 2.21071 2.96086 2.58579 2.58579C2.96086 2.21071 3.46957 2 4 2H13C13.5304 2 14.0391 2.21071 14.4142 2.58579C14.7893 2.96086 15 3.46957 15 4V5M11 9H20C21.1046 9 22 9.89543 22 11V20C22 21.1046 21.1046 22 20 22H11C9.89543 22 9 21.1046 9 20V11C9 9.89543 9.89543 9 11 9Z"
|
||||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
Duplicate
|
Duplicate
|
||||||
</v-button>
|
</v-button>
|
||||||
</div>
|
</div>
|
||||||
<change-field-type class="my-1" :field="field" @changeType="onChangeType"/>
|
<change-field-type class="my-1" :field="field" @changeType="onChangeType" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -125,7 +129,7 @@
|
||||||
</p>
|
</p>
|
||||||
<v-checkbox v-model="field.multi_lines"
|
<v-checkbox v-model="field.multi_lines"
|
||||||
:name="field.id+'_multi_lines'"
|
:name="field.id+'_multi_lines'"
|
||||||
@input="$set(field,'multi_lines',$event)"
|
@input="field.multi_lines = $event"
|
||||||
>
|
>
|
||||||
Multi-lines input
|
Multi-lines input
|
||||||
</v-checkbox>
|
</v-checkbox>
|
||||||
|
@ -194,21 +198,23 @@
|
||||||
Advanced options for your select/multiselect fields.
|
Advanced options for your select/multiselect fields.
|
||||||
</p>
|
</p>
|
||||||
<text-area-input v-model="optionsText" :name="field.id+'_options_text'" class="mt-4"
|
<text-area-input v-model="optionsText" :name="field.id+'_options_text'" class="mt-4"
|
||||||
@input="onFieldOptionsChange"
|
|
||||||
label="Set selection options"
|
label="Set selection options"
|
||||||
help="Add one option per line"
|
help="Add one option per line"
|
||||||
|
@input="onFieldOptionsChange"
|
||||||
/>
|
/>
|
||||||
<v-checkbox v-model="field.allow_creation"
|
<v-checkbox v-model="field.allow_creation"
|
||||||
name="allow_creation" @input="onFieldAllowCreationChange" help=""
|
name="allow_creation" help="" @input="onFieldAllowCreationChange"
|
||||||
>
|
>
|
||||||
Allow respondent to create new options
|
Allow respondent to create new options
|
||||||
</v-checkbox>
|
</v-checkbox>
|
||||||
<v-checkbox v-model="field.without_dropdown" class="mt-4"
|
<v-checkbox v-model="field.without_dropdown" class="mt-4"
|
||||||
name="without_dropdown" @input="onFieldWithoutDropdownChange" help=""
|
name="without_dropdown" help="" @input="onFieldWithoutDropdownChange"
|
||||||
>
|
>
|
||||||
Always show all select options
|
Always show all select options
|
||||||
</v-checkbox>
|
</v-checkbox>
|
||||||
<p class="text-gray-400 mb-5 text-xs">Options won't be in a dropdown anymore, but will all be visible</p>
|
<p class="text-gray-400 mb-5 text-xs">
|
||||||
|
Options won't be in a dropdown anymore, but will all be visible
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Customization - Placeholder, Prefill, Relabel, Field Help -->
|
<!-- Customization - Placeholder, Prefill, Relabel, Field Help -->
|
||||||
|
@ -235,7 +241,7 @@
|
||||||
<!-- Pre-fill depends on type -->
|
<!-- Pre-fill depends on type -->
|
||||||
<v-checkbox v-if="field.type=='checkbox'" v-model="field.prefill" class="mt-4"
|
<v-checkbox v-if="field.type=='checkbox'" v-model="field.prefill" class="mt-4"
|
||||||
:name="field.id+'_prefill'"
|
:name="field.id+'_prefill'"
|
||||||
@input="$set(field,'prefill',$event)"
|
@input="field.prefill = $event"
|
||||||
>
|
>
|
||||||
Pre-filled value
|
Pre-filled value
|
||||||
</v-checkbox>
|
</v-checkbox>
|
||||||
|
@ -286,7 +292,7 @@
|
||||||
<!-- Help -->
|
<!-- Help -->
|
||||||
<rich-text-area-input name="help" class="mt-4"
|
<rich-text-area-input name="help" class="mt-4"
|
||||||
:form="field"
|
:form="field"
|
||||||
:editorToolbar="editorToolbarCustom"
|
:editor-toolbar="editorToolbarCustom"
|
||||||
label="Field Help"
|
label="Field Help"
|
||||||
help="Your field help will be shown below/above the field, just like this message."
|
help="Your field help will be shown below/above the field, just like this message."
|
||||||
:help-position="field.help_position"
|
:help-position="field.help_position"
|
||||||
|
@ -311,7 +317,6 @@
|
||||||
label="Always show character limit"
|
label="Always show character limit"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Advanced Options -->
|
<!-- Advanced Options -->
|
||||||
|
@ -342,7 +347,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Logic Block -->
|
<!-- Logic Block -->
|
||||||
<form-block-logic-editor v-model="form" :form="form" :field="field"/>
|
<form-block-logic-editor v-model="form" :form="form" :field="field" />
|
||||||
|
|
||||||
<div class="pt-5 flex justify-end">
|
<div class="pt-5 flex justify-end">
|
||||||
<v-button color="white" @click="close">
|
<v-button color="white" @click="close">
|
||||||
|
@ -359,14 +364,14 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import timezones from '../../../../../data/timezones.json'
|
import timezones from '../../../../../data/timezones.json'
|
||||||
import ProTag from "../../../common/ProTag.vue"
|
import ProTag from '../../../common/ProTag.vue'
|
||||||
|
import ChangeFieldType from './components/ChangeFieldType.vue'
|
||||||
|
|
||||||
const FormBlockLogicEditor = () => import('../components/form-logic-components/FormBlockLogicEditor.vue')
|
const FormBlockLogicEditor = () => import('../components/form-logic-components/FormBlockLogicEditor.vue')
|
||||||
import ChangeFieldType from "./components/ChangeFieldType.vue"
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'FormFieldOptionsModal',
|
name: 'FormFieldOptionsModal',
|
||||||
components: {ProTag, FormBlockLogicEditor, ChangeFieldType},
|
components: { ProTag, FormBlockLogicEditor, ChangeFieldType },
|
||||||
props: {
|
props: {
|
||||||
field: {
|
field: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -381,20 +386,20 @@ export default {
|
||||||
required: false
|
required: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data () {
|
||||||
return {
|
return {
|
||||||
typesWithoutPlaceholder: ['date', 'checkbox', 'files'],
|
typesWithoutPlaceholder: ['date', 'checkbox', 'files'],
|
||||||
editorToolbarCustom: [
|
editorToolbarCustom: [
|
||||||
['bold', 'italic', 'underline', 'link'],
|
['bold', 'italic', 'underline', 'link']
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
hasPlaceholder() {
|
hasPlaceholder () {
|
||||||
return !this.typesWithoutPlaceholder.includes(this.field.type)
|
return !this.typesWithoutPlaceholder.includes(this.field.type)
|
||||||
},
|
},
|
||||||
prefillSelectsOptions() {
|
prefillSelectsOptions () {
|
||||||
if (!['select', 'multi_select'].includes(this.field.type)) return {}
|
if (!['select', 'multi_select'].includes(this.field.type)) return {}
|
||||||
|
|
||||||
return this.field[this.field.type].options.map(option => {
|
return this.field[this.field.type].options.map(option => {
|
||||||
|
@ -404,7 +409,7 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
timezonesOptions() {
|
timezonesOptions () {
|
||||||
if (this.field.type !== 'date') return []
|
if (this.field.type !== 'date') return []
|
||||||
return timezones.map((timezone) => {
|
return timezones.map((timezone) => {
|
||||||
return {
|
return {
|
||||||
|
@ -413,24 +418,24 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
displayBasedOnAdvanced() {
|
displayBasedOnAdvanced () {
|
||||||
if (this.field.generates_uuid || this.field.generates_auto_increment_id) {
|
if (this.field.generates_uuid || this.field.generates_auto_increment_id) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
optionsText() {
|
optionsText () {
|
||||||
return this.field[this.field.type].options.map(option => {
|
return this.field[this.field.type].options.map(option => {
|
||||||
return option.name
|
return option.name
|
||||||
}).join("\n")
|
}).join('\n')
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
'field.width': {
|
'field.width': {
|
||||||
handler (val) {
|
handler (val) {
|
||||||
if (val === undefined || val === null) {
|
if (val === undefined || val === null) {
|
||||||
this.$set(this.field, 'width', 'full')
|
this.field.width = 'full'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
|
@ -439,139 +444,139 @@ export default {
|
||||||
|
|
||||||
created () {
|
created () {
|
||||||
if (this.field.width === undefined || this.field.width === null) {
|
if (this.field.width === undefined || this.field.width === null) {
|
||||||
this.$set(this.field, 'width', 'full')
|
this.field.width = 'full'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted () {
|
||||||
if (['text', 'number', 'url', 'email', 'phone_number'].includes(this.field.type) && !this.field.max_char_limit) {
|
if (['text', 'number', 'url', 'email', 'phone_number'].includes(this.field.type) && !this.field.max_char_limit) {
|
||||||
this.field.max_char_limit = 2000
|
this.field.max_char_limit = 2000
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onChangeType(newType) {
|
onChangeType (newType) {
|
||||||
if(['select', 'multi_select'].includes(this.field.type)){
|
if (['select', 'multi_select'].includes(this.field.type)) {
|
||||||
this.$set(this.field, newType, this.field[this.field.type]) // Set new options with new type
|
this.field[newType] = this.field[this.field.type] // Set new options with new type
|
||||||
this.$delete(this.field, this.field.type) // remove old type options
|
delete this.field[this.field.type] // remove old type options
|
||||||
}
|
}
|
||||||
this.$set(this.field, 'type', newType)
|
this.field.type = newType
|
||||||
},
|
},
|
||||||
close() {
|
close () {
|
||||||
this.$emit('close')
|
this.$emit('close')
|
||||||
},
|
},
|
||||||
removeBlock() {
|
removeBlock () {
|
||||||
this.close()
|
this.close()
|
||||||
this.$emit('remove-block', this.field)
|
this.$emit('remove-block', this.field)
|
||||||
},
|
},
|
||||||
duplicateBlock() {
|
duplicateBlock () {
|
||||||
this.close()
|
this.close()
|
||||||
this.$emit('duplicate-block', this.field)
|
this.$emit('duplicate-block', this.field)
|
||||||
},
|
},
|
||||||
onFieldDisabledChange (val) {
|
onFieldDisabledChange (val) {
|
||||||
this.$set(this.field, 'disabled', val)
|
this.field.disabled = val
|
||||||
if (this.field.disabled) {
|
if (this.field.disabled) {
|
||||||
this.$set(this.field, 'hidden', false)
|
this.field.hidden = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldRequiredChange(val) {
|
onFieldRequiredChange (val) {
|
||||||
this.$set(this.field, 'required', val)
|
this.field.required = val
|
||||||
if (this.field.required) {
|
if (this.field.required) {
|
||||||
this.$set(this.field, 'hidden', false)
|
this.field.hidden = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldHiddenChange(val) {
|
onFieldHiddenChange (val) {
|
||||||
this.$set(this.field, 'hidden', val)
|
this.field.hidden = val
|
||||||
if (this.field.hidden) {
|
if (this.field.hidden) {
|
||||||
this.$set(this.field, 'required', false)
|
this.field.required = false
|
||||||
this.$set(this.field, 'disabled', false)
|
this.field.disabled = false
|
||||||
} else {
|
} else {
|
||||||
this.$set(this.field, 'generates_uuid', false)
|
this.field.generates_uuid = false
|
||||||
this.$set(this.field, 'generates_auto_increment_id', false)
|
this.field.generates_auto_increment_id = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldDateRangeChange(val) {
|
onFieldDateRangeChange (val) {
|
||||||
this.$set(this.field, 'date_range', val)
|
this.field.date_range = val
|
||||||
if (this.field.date_range) {
|
if (this.field.date_range) {
|
||||||
this.$set(this.field, 'with_time', false)
|
this.field.with_time = false
|
||||||
this.$set(this.field, 'prefill_today', false)
|
this.field.prefill_today = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldWithTimeChange(val) {
|
onFieldWithTimeChange (val) {
|
||||||
this.$set(this.field, 'with_time', val)
|
this.field.with_time = val
|
||||||
if (this.field.with_time) {
|
if (this.field.with_time) {
|
||||||
this.$set(this.field, 'date_range', false)
|
this.field.date_range = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldGenUIdChange(val) {
|
onFieldGenUIdChange (val) {
|
||||||
this.$set(this.field, 'generates_uuid', val)
|
this.field.generates_uuid = val
|
||||||
if (this.field.generates_uuid) {
|
if (this.field.generates_uuid) {
|
||||||
this.$set(this.field, 'generates_auto_increment_id', false)
|
this.field.generates_auto_increment_id = false
|
||||||
this.$set(this.field, 'hidden', true)
|
this.field.hidden = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldGenAutoIdChange(val) {
|
onFieldGenAutoIdChange (val) {
|
||||||
this.$set(this.field, 'generates_auto_increment_id', val)
|
this.field.generates_auto_increment_id = val
|
||||||
if (this.field.generates_auto_increment_id) {
|
if (this.field.generates_auto_increment_id) {
|
||||||
this.$set(this.field, 'generates_uuid', false)
|
this.field.generates_uuid = false
|
||||||
this.$set(this.field, 'hidden', true)
|
this.field.hidden = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
initRating() {
|
initRating () {
|
||||||
if (this.field.is_rating && !this.field.rating_max_value) {
|
if (this.field.is_rating && !this.field.rating_max_value) {
|
||||||
this.$set(this.field, 'rating_max_value', 5)
|
this.field.rating_max_value = 5
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldOptionsChange(val) {
|
onFieldOptionsChange (val) {
|
||||||
const vals = (val) ? val.trim().split("\n") : []
|
const vals = (val) ? val.trim().split('\n') : []
|
||||||
const tmpOpts = vals.map(name => {
|
const tmpOpts = vals.map(name => {
|
||||||
return {
|
return {
|
||||||
name: name,
|
name: name,
|
||||||
id: name
|
id: name
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.$set(this.field, this.field.type, {'options': tmpOpts})
|
this.field[this.field.type] = { options: tmpOpts }
|
||||||
},
|
},
|
||||||
onFieldPrefillTodayChange(val) {
|
onFieldPrefillTodayChange (val) {
|
||||||
this.$set(this.field, 'prefill_today', val)
|
this.field.prefill_today = val
|
||||||
if (this.field.prefill_today) {
|
if (this.field.prefill_today) {
|
||||||
this.$set(this.field, 'prefill', 'Pre-filled with current date')
|
this.field.prefill = 'Pre-filled with current date'
|
||||||
this.$set(this.field, 'date_range', false)
|
this.field.date_range = false
|
||||||
this.$set(this.field, 'disable_future_dates', false)
|
this.field.disable_future_dates = false
|
||||||
this.$set(this.field, 'disable_past_dates', false)
|
this.field.disable_past_dates = false
|
||||||
} else {
|
} else {
|
||||||
this.$set(this.field, 'prefill', null)
|
this.field.prefill = null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldAllowCreationChange(val) {
|
onFieldAllowCreationChange (val) {
|
||||||
this.$set(this.field, 'allow_creation', val)
|
this.field.allow_creation = val
|
||||||
if (this.field.allow_creation) {
|
if (this.field.allow_creation) {
|
||||||
this.$set(this.field, 'without_dropdown', false)
|
this.field.without_dropdown = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldWithoutDropdownChange(val) {
|
onFieldWithoutDropdownChange (val) {
|
||||||
this.$set(this.field, 'without_dropdown', val)
|
this.field.without_dropdown = val
|
||||||
if (this.field.without_dropdown) {
|
if (this.field.without_dropdown) {
|
||||||
this.$set(this.field, 'allow_creation', false)
|
this.field.allow_creation = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldDisablePastDatesChange(val) {
|
onFieldDisablePastDatesChange (val) {
|
||||||
this.$set(this.field, 'disable_past_dates', val)
|
this.field.disable_past_dates = val
|
||||||
if (this.field.disable_past_dates) {
|
if (this.field.disable_past_dates) {
|
||||||
this.$set(this.field, 'disable_future_dates', false)
|
this.field.disable_future_dates = false
|
||||||
this.$set(this.field, 'prefill_today', false)
|
this.field.prefill_today = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldDisableFutureDatesChange(val) {
|
onFieldDisableFutureDatesChange (val) {
|
||||||
this.$set(this.field, 'disable_future_dates', val)
|
this.field.disable_future_dates = val
|
||||||
if (this.field.disable_future_dates) {
|
if (this.field.disable_future_dates) {
|
||||||
this.$set(this.field, 'disable_past_dates', false)
|
this.field.disable_past_dates = false
|
||||||
this.$set(this.field, 'prefill_today', false)
|
this.field.prefill_today = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldHelpPositionChange (val) {
|
onFieldHelpPositionChange (val) {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
this.$set(this.field, 'help_position', 'below_input')
|
this.field.help_position = 'below_input'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ export default {
|
||||||
'field.width': {
|
'field.width': {
|
||||||
handler (val) {
|
handler (val) {
|
||||||
if (val === undefined || val === null) {
|
if (val === undefined || val === null) {
|
||||||
this.$set(this.field, 'width', 'full')
|
this.field.width = 'full'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
|
@ -129,7 +129,7 @@ export default {
|
||||||
'field.align': {
|
'field.align': {
|
||||||
handler (val) {
|
handler (val) {
|
||||||
if (val === undefined || val === null) {
|
if (val === undefined || val === null) {
|
||||||
this.$set(this.field, 'align', 'left')
|
this.field.align = 'left'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
|
@ -138,7 +138,7 @@ export default {
|
||||||
|
|
||||||
created () {
|
created () {
|
||||||
if (this.field?.width === undefined || this.field?.width === null) {
|
if (this.field?.width === undefined || this.field?.width === null) {
|
||||||
this.$set(this.field, 'width', 'full')
|
this.field.width = 'full'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -146,14 +146,14 @@ export default {
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onFieldHiddenChange (val) {
|
onFieldHiddenChange (val) {
|
||||||
this.$set(this.field, 'hidden', val)
|
this.field.hidden = val
|
||||||
if (this.field.hidden) {
|
if (this.field.hidden) {
|
||||||
this.$set(this.field, 'required', false)
|
this.field.required = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldHelpPositionChange (val) {
|
onFieldHelpPositionChange (val) {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
this.$set(this.field, 'help_position', 'below_input')
|
this.field.help_position = 'below_input'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@
|
||||||
</p>
|
</p>
|
||||||
<v-checkbox v-model="field.multi_lines" class="mb-2"
|
<v-checkbox v-model="field.multi_lines" class="mb-2"
|
||||||
:name="field.id+'_multi_lines'"
|
:name="field.id+'_multi_lines'"
|
||||||
@input="$set(field,'multi_lines',$event)"
|
@input="field.multi_lines = $event"
|
||||||
>
|
>
|
||||||
Multi-lines input
|
Multi-lines input
|
||||||
</v-checkbox>
|
</v-checkbox>
|
||||||
|
@ -243,7 +243,7 @@
|
||||||
<!-- Pre-fill depends on type -->
|
<!-- Pre-fill depends on type -->
|
||||||
<v-checkbox v-if="field.type=='checkbox'" v-model="field.prefill" class="mt-3"
|
<v-checkbox v-if="field.type=='checkbox'" v-model="field.prefill" class="mt-3"
|
||||||
:name="field.id+'_prefill'"
|
:name="field.id+'_prefill'"
|
||||||
@input="$set(field,'prefill',$event)"
|
@input="field.prefill =$event"
|
||||||
>
|
>
|
||||||
Pre-filled value
|
Pre-filled value
|
||||||
</v-checkbox>
|
</v-checkbox>
|
||||||
|
@ -363,6 +363,7 @@
|
||||||
import timezones from '../../../../../../data/timezones.json'
|
import timezones from '../../../../../../data/timezones.json'
|
||||||
import countryCodes from '../../../../../../data/country_codes.json'
|
import countryCodes from '../../../../../../data/country_codes.json'
|
||||||
import CountryFlag from 'vue-country-flag-next'
|
import CountryFlag from 'vue-country-flag-next'
|
||||||
|
|
||||||
const FormBlockLogicEditor = () => import('../../components/form-logic-components/FormBlockLogicEditor.vue')
|
const FormBlockLogicEditor = () => import('../../components/form-logic-components/FormBlockLogicEditor.vue')
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -428,7 +429,7 @@ export default {
|
||||||
'field.width': {
|
'field.width': {
|
||||||
handler (val) {
|
handler (val) {
|
||||||
if (val === undefined || val === null) {
|
if (val === undefined || val === null) {
|
||||||
this.$set(this.field, 'width', 'full')
|
this.field.width = 'full'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
|
@ -436,7 +437,7 @@ export default {
|
||||||
'field.align': {
|
'field.align': {
|
||||||
handler (val) {
|
handler (val) {
|
||||||
if (val === undefined || val === null) {
|
if (val === undefined || val === null) {
|
||||||
this.$set(this.field, 'align', 'left')
|
this.field.align = 'left'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
|
@ -445,7 +446,7 @@ export default {
|
||||||
|
|
||||||
created () {
|
created () {
|
||||||
if (this.field?.width === undefined || this.field?.width === null) {
|
if (this.field?.width === undefined || this.field?.width === null) {
|
||||||
this.$set(this.field, 'width', 'full')
|
this.field.width = 'full'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -457,57 +458,57 @@ export default {
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onFieldDisabledChange (val) {
|
onFieldDisabledChange (val) {
|
||||||
this.$set(this.field, 'disabled', val)
|
this.field.disabled = val
|
||||||
if (this.field.disabled) {
|
if (this.field.disabled) {
|
||||||
this.$set(this.field, 'hidden', false)
|
this.field.hidden = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldRequiredChange (val) {
|
onFieldRequiredChange (val) {
|
||||||
this.$set(this.field, 'required', val)
|
this.field.required = val
|
||||||
if (this.field.required) {
|
if (this.field.required) {
|
||||||
this.$set(this.field, 'hidden', false)
|
this.field.hidden = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldHiddenChange (val) {
|
onFieldHiddenChange (val) {
|
||||||
this.$set(this.field, 'hidden', val)
|
this.field.hidden = val
|
||||||
if (this.field.hidden) {
|
if (this.field.hidden) {
|
||||||
this.$set(this.field, 'required', false)
|
this.field.required = false
|
||||||
this.$set(this.field, 'disabled', false)
|
this.field.disabled = false
|
||||||
} else {
|
} else {
|
||||||
this.$set(this.field, 'generates_uuid', false)
|
this.field.generates_uuid = false
|
||||||
this.$set(this.field, 'generates_auto_increment_id', false)
|
this.field.generates_auto_increment_id = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldDateRangeChange (val) {
|
onFieldDateRangeChange (val) {
|
||||||
this.$set(this.field, 'date_range', val)
|
this.field.date_range = val
|
||||||
if (this.field.date_range) {
|
if (this.field.date_range) {
|
||||||
this.$set(this.field, 'with_time', false)
|
this.field.with_time = false
|
||||||
this.$set(this.field, 'prefill_today', false)
|
this.field.prefill_today = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldWithTimeChange (val) {
|
onFieldWithTimeChange (val) {
|
||||||
this.$set(this.field, 'with_time', val)
|
this.field.with_time = val
|
||||||
if (this.field.with_time) {
|
if (this.field.with_time) {
|
||||||
this.$set(this.field, 'date_range', false)
|
this.field.date_range = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldGenUIdChange (val) {
|
onFieldGenUIdChange (val) {
|
||||||
this.$set(this.field, 'generates_uuid', val)
|
this.field.generates_uuid = val
|
||||||
if (this.field.generates_uuid) {
|
if (this.field.generates_uuid) {
|
||||||
this.$set(this.field, 'generates_auto_increment_id', false)
|
this.field.generates_auto_increment_id = false
|
||||||
this.$set(this.field, 'hidden', true)
|
this.field.hidden = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldGenAutoIdChange (val) {
|
onFieldGenAutoIdChange (val) {
|
||||||
this.$set(this.field, 'generates_auto_increment_id', val)
|
this.field.generates_auto_increment_id = val
|
||||||
if (this.field.generates_auto_increment_id) {
|
if (this.field.generates_auto_increment_id) {
|
||||||
this.$set(this.field, 'generates_uuid', false)
|
this.field.generates_uuid = false
|
||||||
this.$set(this.field, 'hidden', true)
|
this.field.hidden = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
initRating () {
|
initRating () {
|
||||||
if (this.field.is_rating && !this.field.rating_max_value) {
|
if (this.field.is_rating && !this.field.rating_max_value) {
|
||||||
this.$set(this.field, 'rating_max_value', 5)
|
this.field.rating_max_value = 5
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldOptionsChange (val) {
|
onFieldOptionsChange (val) {
|
||||||
|
@ -518,54 +519,54 @@ export default {
|
||||||
id: name
|
id: name
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.$set(this.field, this.field.type, { options: tmpOpts })
|
this.field[this.field.type] = { options: tmpOpts }
|
||||||
},
|
},
|
||||||
onFieldPrefillTodayChange (val) {
|
onFieldPrefillTodayChange (val) {
|
||||||
this.$set(this.field, 'prefill_today', val)
|
this.field.prefill_today = val
|
||||||
if (this.field.prefill_today) {
|
if (this.field.prefill_today) {
|
||||||
this.$set(this.field, 'prefill', 'Pre-filled with current date')
|
this.field.prefill = 'Pre-filled with current date'
|
||||||
this.$set(this.field, 'date_range', false)
|
this.field.date_range = false
|
||||||
this.$set(this.field, 'disable_future_dates', false)
|
this.field.disable_future_dates = false
|
||||||
this.$set(this.field, 'disable_past_dates', false)
|
this.field.disable_past_dates = false
|
||||||
} else {
|
} else {
|
||||||
this.$set(this.field, 'prefill', null)
|
this.field.prefill = null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldAllowCreationChange (val) {
|
onFieldAllowCreationChange (val) {
|
||||||
this.$set(this.field, 'allow_creation', val)
|
this.field.allow_creation = val
|
||||||
if (this.field.allow_creation) {
|
if (this.field.allow_creation) {
|
||||||
this.$set(this.field, 'without_dropdown', false)
|
this.field.without_dropdown = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldWithoutDropdownChange (val) {
|
onFieldWithoutDropdownChange (val) {
|
||||||
this.$set(this.field, 'without_dropdown', val)
|
this.field.without_dropdown = val
|
||||||
if (this.field.without_dropdown) {
|
if (this.field.without_dropdown) {
|
||||||
this.$set(this.field, 'allow_creation', false)
|
this.field.allow_creation = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldDisablePastDatesChange (val) {
|
onFieldDisablePastDatesChange (val) {
|
||||||
this.$set(this.field, 'disable_past_dates', val)
|
this.field.disable_past_dates = val
|
||||||
if (this.field.disable_past_dates) {
|
if (this.field.disable_past_dates) {
|
||||||
this.$set(this.field, 'disable_future_dates', false)
|
this.field.disable_future_dates = false
|
||||||
this.$set(this.field, 'prefill_today', false)
|
this.field.prefill_today = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldDisableFutureDatesChange (val) {
|
onFieldDisableFutureDatesChange (val) {
|
||||||
this.$set(this.field, 'disable_future_dates', val)
|
this.field.disable_future_dates = val
|
||||||
if (this.field.disable_future_dates) {
|
if (this.field.disable_future_dates) {
|
||||||
this.$set(this.field, 'disable_past_dates', false)
|
this.field.disable_past_dates = false
|
||||||
this.$set(this.field, 'prefill_today', false)
|
this.field.prefill_today = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldHelpPositionChange (val) {
|
onFieldHelpPositionChange (val) {
|
||||||
if (!val) {
|
if (!val) {
|
||||||
this.$set(this.field, 'help_position', 'below_input')
|
this.field.help_position = 'below_input'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
selectAllCountries () {
|
selectAllCountries () {
|
||||||
this.$set(this.field, 'unavailable_countries', this.allCountries.map(item => {
|
this.field.unavailable_countries = this.allCountries.map(item => {
|
||||||
return item.code
|
return item.code
|
||||||
}))
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,7 +232,7 @@ export default {
|
||||||
const columns = clonedeep(this.form.properties)
|
const columns = clonedeep(this.form.properties)
|
||||||
const index = this.form.properties.findIndex(c => c.id === col.id)
|
const index = this.form.properties.findIndex(c => c.id === col.id)
|
||||||
columns[index].cell_width = width
|
columns[index].cell_width = width
|
||||||
this.$set(this.form, 'properties', columns)
|
this.form.properties = columns
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$emit('resize')
|
this.$emit('resize')
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<v-button
|
<v-button
|
||||||
|
v-track.share_embed_form_popup_click="{form_id:form.id, form_slug:form.slug}"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
color="light-gray"
|
color="light-gray"
|
||||||
v-track.share_embed_form_popup_click="{form_id:form.id, form_slug:form.slug}"
|
|
||||||
@click="showEmbedFormAsPopupModal=true"
|
@click="showEmbedFormAsPopupModal=true"
|
||||||
>
|
>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 mr-4 text-blue-600 inline" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 mr-4 text-blue-600 inline" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<collapse class="py-5 w-full border rounded-md px-4" :default-value="false">
|
<collapse class="py-5 w-full border rounded-md px-4" :model-value="false">
|
||||||
<template #title>
|
<template #title>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<h3 class="font-semibold block text-lg">
|
<h3 class="font-semibold block text-lg">
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="border border-gray-300 rounded-xl flex p-1 relative">
|
<div class="border border-gray-300 rounded-xl flex p-1 relative">
|
||||||
<button class="font-semibold block flex-grow cursor-pointer">
|
<button class="font-semibold block flex-grow cursor-pointer">
|
||||||
<div class="p-2 px-3 rounded-lg transition-colors" :class="{'bg-blue-500 text-white':!value}"
|
<div
|
||||||
|
class="p-2 px-3 rounded-lg transition-colors"
|
||||||
|
:class="{'bg-blue-500 text-white': !modelValue}"
|
||||||
@click="set(false)"
|
@click="set(false)"
|
||||||
>
|
>
|
||||||
Monthly
|
Monthly
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button class="font-semibold block flex-grow cursor-pointer" @click="set(true)">
|
<button class="font-semibold block flex-grow cursor-pointer" @click="set(true)">
|
||||||
<div class="p-2 px-4 rounded-lg transition-colors" :class="{'bg-blue-500 text-white':value}">
|
<div
|
||||||
|
class="p-2 px-4 rounded-lg transition-colors"
|
||||||
|
:class="{'bg-blue-500 text-white': modelValue}"
|
||||||
|
>
|
||||||
Yearly
|
Yearly
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
@ -18,24 +23,15 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
import { defineEmits, defineProps } from 'vue'
|
||||||
|
|
||||||
components: {},
|
defineProps({
|
||||||
props: {
|
modelValue: { type: Boolean, required: true }
|
||||||
value: {
|
})
|
||||||
type: Boolean,
|
const emit = defineEmits()
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: () => ({}),
|
|
||||||
|
|
||||||
computed: {},
|
const set = (value) => {
|
||||||
|
emit('update:modelValue', value)
|
||||||
methods: {
|
|
||||||
set (value) {
|
|
||||||
this.$emit('input', value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<section class="relative">
|
<section class="relative">
|
||||||
<div v-if="!homePage" class="absolute inset-0 grid" aria-hidden="true">
|
<div v-if="!homePage" class="absolute inset-0 grid" aria-hidden="true">
|
||||||
<div class="bg-gray-100"></div>
|
<div class="bg-gray-100" />
|
||||||
<div class="bg-white"></div>
|
<div class="bg-white" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="px-4 mx-auto max-w-7xl sm:px-6 lg:px-8">
|
<div class="px-4 mx-auto max-w-7xl sm:px-6 lg:px-8">
|
||||||
|
@ -14,13 +14,14 @@
|
||||||
<span class="ml-2 text-nt-blue">
|
<span class="ml-2 text-nt-blue">
|
||||||
<svg class="inline w-10 h-10" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="inline w-10 h-10" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<g opacity="0.12">
|
<g opacity="0.12">
|
||||||
<path d="M15.9998 27.3333L10.6665 12H21.3332L15.9998 27.3333Z" fill="currentColor"/>
|
<path d="M15.9998 27.3333L10.6665 12H21.3332L15.9998 27.3333Z" fill="currentColor" />
|
||||||
<path d="M13.3332 4H9.33317L2.6665 12L10.6665 12L13.3332 4Z" fill="currentColor"/>
|
<path d="M13.3332 4H9.33317L2.6665 12L10.6665 12L13.3332 4Z" fill="currentColor" />
|
||||||
<path d="M18.6665 4H22.6665L29.3332 12L21.3332 12L18.6665 4Z" fill="currentColor"/>
|
<path d="M18.6665 4H22.6665L29.3332 12L21.3332 12L18.6665 4Z" fill="currentColor" />
|
||||||
</g>
|
</g>
|
||||||
<path
|
<path
|
||||||
d="M3.33345 12H28.6668M13.3334 4L10.6668 12L16.0001 27.3333L21.3334 12L18.6668 4M16.8195 27.0167L28.7644 12.6829C28.9668 12.4399 29.0681 12.3185 29.1067 12.1829C29.1408 12.0633 29.1408 11.9367 29.1067 11.8171C29.0681 11.6815 28.9668 11.5601 28.7644 11.3171L22.9866 4.3838C22.8691 4.24273 22.8103 4.17219 22.7382 4.12148C22.6744 4.07654 22.6031 4.04318 22.5277 4.02289C22.4426 4 22.3508 4 22.1672 4H9.83305C9.64941 4 9.55758 4 9.4725 4.02289C9.39711 4.04318 9.32586 4.07654 9.26202 4.12148C9.18996 4.17219 9.13118 4.24273 9.01361 4.3838L3.23583 11.3171C3.0334 11.5601 2.93218 11.6815 2.8935 11.8171C2.85939 11.9366 2.85939 12.0633 2.8935 12.1829C2.93218 12.3185 3.0334 12.4399 3.23583 12.6829L15.1807 27.0167C15.4621 27.3544 15.6028 27.5232 15.7713 27.5848C15.919 27.6388 16.0812 27.6388 16.229 27.5848C16.3974 27.5232 16.5381 27.3544 16.8195 27.0167Z"
|
d="M3.33345 12H28.6668M13.3334 4L10.6668 12L16.0001 27.3333L21.3334 12L18.6668 4M16.8195 27.0167L28.7644 12.6829C28.9668 12.4399 29.0681 12.3185 29.1067 12.1829C29.1408 12.0633 29.1408 11.9367 29.1067 11.8171C29.0681 11.6815 28.9668 11.5601 28.7644 11.3171L22.9866 4.3838C22.8691 4.24273 22.8103 4.17219 22.7382 4.12148C22.6744 4.07654 22.6031 4.04318 22.5277 4.02289C22.4426 4 22.3508 4 22.1672 4H9.83305C9.64941 4 9.55758 4 9.4725 4.02289C9.39711 4.04318 9.32586 4.07654 9.26202 4.12148C9.18996 4.17219 9.13118 4.24273 9.01361 4.3838L3.23583 11.3171C3.0334 11.5601 2.93218 11.6815 2.8935 11.8171C2.85939 11.9366 2.85939 12.0633 2.8935 12.1829C2.93218 12.3185 3.0334 12.4399 3.23583 12.6829L15.1807 27.0167C15.4621 27.3544 15.6028 27.5232 15.7713 27.5848C15.919 27.6388 16.0812 27.6388 16.229 27.5848C16.3974 27.5232 16.5381 27.3544 16.8195 27.0167Z"
|
||||||
stroke="currentColor" stroke-width="2.66667" stroke-linecap="round" stroke-linejoin="round"/>
|
stroke="currentColor" stroke-width="2.66667" stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
Pro Features
|
Pro Features
|
||||||
</span>
|
</span>
|
||||||
|
@ -37,28 +38,31 @@
|
||||||
<h4 class="flex-none text-sm font-semibold leading-6 tracking-widest text-gray-400 uppercase">
|
<h4 class="flex-none text-sm font-semibold leading-6 tracking-widest text-gray-400 uppercase">
|
||||||
What's included
|
What's included
|
||||||
</h4>
|
</h4>
|
||||||
<div class="flex-auto h-px bg-gray-200"></div>
|
<div class="flex-auto h-px bg-gray-200" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul role="list"
|
<ul role="list"
|
||||||
class="grid grid-cols-1 gap-4 mt-4 text-sm font-medium leading-6 text-gray-900 sm:grid-cols-2 sm:gap-x-6 sm:gap-y-2">
|
class="grid grid-cols-1 gap-4 mt-4 text-sm font-medium leading-6 text-gray-900 sm:grid-cols-2 sm:gap-x-6 sm:gap-y-2"
|
||||||
|
>
|
||||||
<li v-for="(title, i) in pricingInfo" :key="i" class="flex gap-x-3">
|
<li v-for="(title, i) in pricingInfo" :key="i" class="flex gap-x-3">
|
||||||
<svg aria-hidden="true" class="w-5 h-5 shrink-0 stroke-blue-600" viewBox="0 0 24 24" fill="none"
|
<svg aria-hidden="true" class="w-5 h-5 shrink-0 stroke-blue-600" viewBox="0 0 24 24" fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
<path d="M20 6L9 17L4 12" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
>
|
||||||
|
<path d="M20 6L9 17L4 12" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
</svg>
|
</svg>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</li>
|
</li>
|
||||||
<slot name="pricing-table"></slot>
|
<slot name="pricing-table" />
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-2 -mt-2 flex-col lg:mt-0 lg:w-full lg:max-w-md lg:flex-shrink-0">
|
<div class="p-2 -mt-2 flex-col lg:mt-0 lg:w-full lg:max-w-md lg:flex-shrink-0">
|
||||||
<div
|
<div
|
||||||
class="grow h-full py-10 text-center rounded-2xl bg-gray-50 ring-1 ring-inset ring-gray-900/5 lg:flex lg:flex-col lg:justify-center lg:py-12">
|
class="grow h-full py-10 text-center rounded-2xl bg-gray-50 ring-1 ring-inset ring-gray-900/5 lg:flex lg:flex-col lg:justify-center lg:py-12"
|
||||||
|
>
|
||||||
<div class="max-w-xs px-8 mx-auto space-y-6">
|
<div class="max-w-xs px-8 mx-auto space-y-6">
|
||||||
<div class="flex items-center justify-center mb-10">
|
<div class="flex items-center justify-center mb-10">
|
||||||
<monthly-yearly-selector v-model="isYearly"/>
|
<monthly-yearly-selector v-model="isYearly" />
|
||||||
</div><!-- lg+ -->
|
</div><!-- lg+ -->
|
||||||
|
|
||||||
<p class="flex flex-col items-center">
|
<p class="flex flex-col items-center">
|
||||||
|
@ -75,11 +79,12 @@
|
||||||
<v-button v-if="!authenticated" class="mr-1" :to="{ name: 'register' }" :arrow="true">
|
<v-button v-if="!authenticated" class="mr-1" :to="{ name: 'register' }" :arrow="true">
|
||||||
Start free trial
|
Start free trial
|
||||||
</v-button>
|
</v-button>
|
||||||
<v-button v-else-if="authenticated && user.is_subscribed" class="mr-1" @click.prevent="openBilling"
|
<v-button v-else-if="authenticated && user.is_subscribed" class="mr-1" :arrow="true"
|
||||||
:arrow="true">
|
@click.prevent="openBilling"
|
||||||
|
>
|
||||||
View Billing
|
View Billing
|
||||||
</v-button>
|
</v-button>
|
||||||
<v-button v-else class="mr-1" @click.prevent="openCustomerCheckout('default')" :arrow="true">
|
<v-button v-else class="mr-1" :arrow="true" @click.prevent="openCustomerCheckout('default')">
|
||||||
Start free trial
|
Start free trial
|
||||||
</v-button>
|
</v-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -100,15 +105,17 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {mapGetters} from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import MonthlyYearlySelector from './MonthlyYearlySelector.vue'
|
import MonthlyYearlySelector from './MonthlyYearlySelector.vue'
|
||||||
import CheckoutDetailsModal from './CheckoutDetailsModal.vue'
|
import CheckoutDetailsModal from './CheckoutDetailsModal.vue'
|
||||||
|
|
||||||
|
MonthlyYearlySelector.compatConfig = { MODE: 3 }
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
MonthlyYearlySelector,
|
MonthlyYearlySelector,
|
||||||
CheckoutDetailsModal,
|
CheckoutDetailsModal
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
homePage: {
|
homePage: {
|
||||||
|
@ -135,11 +142,11 @@ export default {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
openCustomerCheckout(plan) {
|
openCustomerCheckout (plan) {
|
||||||
this.selectedPlan = plan
|
this.selectedPlan = plan
|
||||||
this.showDetailsModal = true
|
this.showDetailsModal = true
|
||||||
},
|
},
|
||||||
openBilling() {
|
openBilling () {
|
||||||
this.billingLoading = true
|
this.billingLoading = true
|
||||||
axios.get('/api/subscription/billing-portal').then((response) => {
|
axios.get('/api/subscription/billing-portal').then((response) => {
|
||||||
this.billingLoading = false
|
this.billingLoading = false
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="mx-auto mb-12 max-w-7xl px-6 lg:px-8">
|
<div class="mx-auto mb-12 max-w-7xl px-6 lg:px-8">
|
||||||
<div class="mx-auto max-w-2xl text-center">
|
<div class="mx-auto max-w-2xl text-center">
|
||||||
<h2 class="text-lg font-semibold leading-8 tracking-tight text-blue-500 ">Single or multi-page forms</h2>
|
<h2 class="text-lg font-semibold leading-8 tracking-tight text-blue-500 ">
|
||||||
<p class="mt-2 text-3xl font-semibold tracking-tight text-gray-900 sm:text-4xl">Discover our beautiful templates</p>
|
Single or multi-page forms
|
||||||
<p class="mt-3 px-8 text-center text-lg text-gray-400 ">If you need inspiration, checkout our templates.</p>
|
</h2>
|
||||||
|
<p class="mt-2 text-3xl font-semibold tracking-tight text-gray-900 sm:text-4xl">
|
||||||
|
Discover our beautiful templates
|
||||||
|
</p>
|
||||||
|
<p class="mt-3 px-8 text-center text-lg text-gray-400 ">
|
||||||
|
If you need inspiration, checkout our templates.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="my-3 flex justify-center">
|
<div class="my-3 flex justify-center">
|
||||||
<router-link :to="{name:'templates'}">
|
<router-link :to="{name:'templates'}">
|
||||||
|
@ -46,21 +52,24 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
templates () {
|
templates: {
|
||||||
|
deep: true,
|
||||||
|
handler () {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.setInfinite()
|
this.setInfinite()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted () {
|
||||||
store.dispatch('open/templates/loadWithLimit', 10)
|
store.dispatch('open/templates/loadWithLimit', 10)
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
setInfinite() {
|
setInfinite () {
|
||||||
let ul = this.$refs['templates-slider']
|
const ul = this.$refs['templates-slider']
|
||||||
if(ul){
|
if (ul) {
|
||||||
ul.insertAdjacentHTML('afterend', ul.outerHTML)
|
ul.insertAdjacentHTML('afterend', ul.outerHTML)
|
||||||
ul.nextSibling.setAttribute('aria-hidden', 'true')
|
ul.nextSibling.setAttribute('aria-hidden', 'true')
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ export default {
|
||||||
compVal: {
|
compVal: {
|
||||||
set (val) {
|
set (val) {
|
||||||
if (this.form) {
|
if (this.form) {
|
||||||
this.$set(this.form, this.name, val)
|
this.form[this.name] = val
|
||||||
} else {
|
} else {
|
||||||
this.content = val
|
this.content = val
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue