opnform-host-nginx/client/components/open/forms/fields/FormFieldEdit.vue

243 lines
7.2 KiB
Vue

<template>
<div>
<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"
>
<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"
stroke-linejoin="round"
/>
</svg>
</button>
<template v-else>
<div class="flex">
<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"
>
<path
d="M18 6L6 18M6 6L18 18"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</button>
<div class="font-semibold inline ml-2 truncate flex-grow truncate">
Configure "<span class="truncate">{{ field.name }}</span>"
</div>
</div>
<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"
@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"
>
<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>
Remove
</v-button>
<v-button
size="small"
class="text-xs"
:class="{
'rounded-none border-r-0': !isBlockField && typeCanBeChanged,
'rounded-l-none': isBlockField || !typeCanBeChanged,
}"
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"
>
<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>
Duplicate
</v-button>
<change-field-type
v-if="!isBlockField"
btn-classes="rounded-l-none text-xs"
:field="field"
@change-type="onChangeType"
/>
</div>
</template>
</div>
<template v-if="field">
<field-options
v-if="!isBlockField"
:form="form"
:field="field"
/>
<block-options
v-if="isBlockField"
:form="form"
:field="field"
/>
</template>
<div
v-else
class="text-center p-10"
>
Click on field's setting icon in your form to modify it
</div>
</div>
</template>
<script>
import { computed } from "vue"
import clonedeep from "clone-deep"
import { useWorkingFormStore } from "../../../../stores/working_form"
import ChangeFieldType from "./components/ChangeFieldType.vue"
import FieldOptions from "./components/FieldOptions.vue"
import BlockOptions from "./components/BlockOptions.vue"
export default {
name: "FormFieldEdit",
components: { ChangeFieldType, FieldOptions, BlockOptions },
props: {},
setup() {
const workingFormStore = useWorkingFormStore()
return {
workingFormStore,
selectedFieldIndex: computed(() => workingFormStore.selectedFieldIndex),
}
},
data() {
return {}
},
computed: {
form: {
get() {
return this.workingFormStore.content
},
/* We add a setter */
set(value) {
this.workingFormStore.set(value)
},
},
field() {
return this.form && this.selectedFieldIndex !== null
? this.form.properties[this.selectedFieldIndex]
: null
},
isBlockField() {
return this.field && this.field.type.startsWith("nf")
},
typeCanBeChanged() {
return [
"text",
"email",
"phone_number",
"number",
"select",
"multi_select",
"rating",
"scale",
"slider",
].includes(this.field.type)
},
},
watch: {},
created() {},
mounted() {},
methods: {
onChangeType(newType) {
if (["select", "multi_select"].includes(this.field.type)) {
this.field[newType] = this.field[this.field.type] // Set new options with new type
delete this.field[this.field.type] // remove old type options
}
this.field.type = newType
},
removeBlock() {
const newFields = clonedeep(this.form.properties)
newFields.splice(this.selectedFieldIndex, 1)
this.form.properties = newFields
this.closeSidebar()
},
duplicateBlock() {
const newFields = clonedeep(this.form.properties)
const newField = clonedeep(this.form.properties[this.selectedFieldIndex])
newField.id = this.generateUUID()
newFields.push(newField)
this.form.properties = newFields
this.closeSidebar()
},
closeSidebar() {
this.workingFormStore.closeEditFieldSidebar()
},
generateUUID() {
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
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
/[xy]/g,
function (c) {
let r = Math.random() * 16 // random number between 0 and 16
if (d > 0) {
// Use timestamp until depleted
r = (d + r) % 16 | 0
d = Math.floor(d / 16)
} else {
// Use microseconds since page-load if supported
r = (d2 + r) % 16 | 0
d2 = Math.floor(d2 / 16)
}
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16)
},
)
},
},
}
</script>