remember builder selected field type
This commit is contained in:
@@ -166,9 +166,10 @@
|
|||||||
:allow-draw="!onlyDefinedFields"
|
:allow-draw="!onlyDefinedFields"
|
||||||
:default-submitters="defaultSubmitters"
|
:default-submitters="defaultSubmitters"
|
||||||
:draw-field="drawField"
|
:draw-field="drawField"
|
||||||
|
:draw-field-type="drawFieldType"
|
||||||
:editable="editable"
|
:editable="editable"
|
||||||
:base-url="baseUrl"
|
:base-url="baseUrl"
|
||||||
@draw="onDraw"
|
@draw="[onDraw($event), withSelectedFieldType ? '' : drawFieldType = '', showDrawField = false]"
|
||||||
@drop-field="onDropfield"
|
@drop-field="onDropfield"
|
||||||
@remove-area="removeArea"
|
@remove-area="removeArea"
|
||||||
/>
|
/>
|
||||||
@@ -210,13 +211,13 @@
|
|||||||
:class="drawField ? 'overflow-hidden' : 'overflow-y-auto overflow-x-hidden'"
|
:class="drawField ? 'overflow-hidden' : 'overflow-y-auto overflow-x-hidden'"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="drawField"
|
v-if="showDrawField || drawField"
|
||||||
class="sticky inset-0 h-full z-20"
|
class="sticky inset-0 h-full z-20"
|
||||||
:style="{ backgroundColor }"
|
:style="{ backgroundColor }"
|
||||||
>
|
>
|
||||||
<div class="bg-base-300 rounded-lg p-5 text-center space-y-4">
|
<div class="bg-base-200 rounded-lg p-5 text-center space-y-4">
|
||||||
<p>
|
<p>
|
||||||
{{ t('draw_field_on_the_document').replace('{field}', drawField.name) }}
|
{{ t('draw_field_on_the_document').replace('{field}', drawField?.name || '') }}
|
||||||
</p>
|
</p>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
@@ -226,10 +227,10 @@
|
|||||||
{{ t('cancel') }}
|
{{ t('cancel') }}
|
||||||
</button>
|
</button>
|
||||||
<a
|
<a
|
||||||
v-if="!drawOption && !drawField.areas.length && !['stamp', 'signature', 'initials'].includes(drawField.type)"
|
v-if="!drawField && !drawOption && !['stamp', 'signature', 'initials'].includes(drawField?.type || drawFieldType)"
|
||||||
href="#"
|
href="#"
|
||||||
class="link block mt-3 text-sm"
|
class="link block mt-3 text-sm"
|
||||||
@click.prevent="[drawField = null, drawOption = null]"
|
@click.prevent="[addField(drawFieldType), drawField = null, drawOption = null, withSelectedFieldType ? '' : drawFieldType = '', showDrawField = false]"
|
||||||
>
|
>
|
||||||
{{ t('or_add_field_without_drawing') }}
|
{{ t('or_add_field_without_drawing') }}
|
||||||
</a>
|
</a>
|
||||||
@@ -244,12 +245,15 @@
|
|||||||
:selected-submitter="selectedSubmitter"
|
:selected-submitter="selectedSubmitter"
|
||||||
:with-help="withHelp"
|
:with-help="withHelp"
|
||||||
:default-submitters="defaultSubmitters"
|
:default-submitters="defaultSubmitters"
|
||||||
|
:draw-field-type="drawFieldType"
|
||||||
:default-fields="defaultFields"
|
:default-fields="defaultFields"
|
||||||
:field-types="fieldTypes"
|
:field-types="fieldTypes"
|
||||||
:with-sticky-submitters="withStickySubmitters"
|
:with-sticky-submitters="withStickySubmitters"
|
||||||
:only-defined-fields="onlyDefinedFields"
|
:only-defined-fields="onlyDefinedFields"
|
||||||
:editable="editable"
|
:editable="editable"
|
||||||
|
@add-field="addField"
|
||||||
@set-draw="[drawField = $event.field, drawOption = $event.option]"
|
@set-draw="[drawField = $event.field, drawOption = $event.option]"
|
||||||
|
@set-draw-type="[drawFieldType = $event, showDrawField = true]"
|
||||||
@set-drag="dragField = $event"
|
@set-drag="dragField = $event"
|
||||||
@change-submitter="selectedSubmitter = $event"
|
@change-submitter="selectedSubmitter = $event"
|
||||||
@drag-end="dragField = null"
|
@drag-end="dragField = null"
|
||||||
@@ -375,6 +379,11 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: () => []
|
default: () => []
|
||||||
},
|
},
|
||||||
|
withSelectedFieldType: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
defaultDrawFieldType: {
|
defaultDrawFieldType: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -491,7 +500,9 @@ export default {
|
|||||||
isBreakpointLg: false,
|
isBreakpointLg: false,
|
||||||
isSaving: false,
|
isSaving: false,
|
||||||
selectedSubmitter: null,
|
selectedSubmitter: null,
|
||||||
|
showDrawField: false,
|
||||||
drawField: null,
|
drawField: null,
|
||||||
|
drawFieldType: null,
|
||||||
drawOption: null,
|
drawOption: null,
|
||||||
dragField: null
|
dragField: null
|
||||||
}
|
}
|
||||||
@@ -574,6 +585,34 @@ export default {
|
|||||||
t (key) {
|
t (key) {
|
||||||
return this.i18n[key] || i18nEn[key] || key
|
return this.i18n[key] || i18nEn[key] || key
|
||||||
},
|
},
|
||||||
|
addField (type, area = null) {
|
||||||
|
const field = {
|
||||||
|
name: '',
|
||||||
|
uuid: v4(),
|
||||||
|
required: type !== 'checkbox',
|
||||||
|
areas: area ? [area] : [],
|
||||||
|
submitter_uuid: this.selectedSubmitter.uuid,
|
||||||
|
type
|
||||||
|
}
|
||||||
|
|
||||||
|
if (['select', 'multiple', 'radio'].includes(type)) {
|
||||||
|
field.options = [{ value: '', uuid: v4() }]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'stamp') {
|
||||||
|
field.readonly = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'date') {
|
||||||
|
field.preferences = {
|
||||||
|
format: Intl.DateTimeFormat().resolvedOptions().locale.endsWith('-US') ? 'MM/DD/YYYY' : 'DD/MM/YYYY'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.template.fields.push(field)
|
||||||
|
|
||||||
|
this.save()
|
||||||
|
},
|
||||||
startFieldDraw ({ name, type }) {
|
startFieldDraw ({ name, type }) {
|
||||||
const existingField = this.template.fields?.find((f) => f.submitter_uuid === this.selectedSubmitter.uuid && name && name === f.name)
|
const existingField = this.template.fields?.find((f) => f.submitter_uuid === this.selectedSubmitter.uuid && name && name === f.name)
|
||||||
|
|
||||||
@@ -654,15 +693,13 @@ export default {
|
|||||||
ref.$el.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
ref.$el.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
||||||
},
|
},
|
||||||
clearDrawField () {
|
clearDrawField () {
|
||||||
if (this.drawField && !this.drawOption && this.drawField.areas.length === 0) {
|
|
||||||
const fieldIndex = this.template.fields.indexOf(this.drawField)
|
|
||||||
|
|
||||||
if (fieldIndex !== -1) {
|
|
||||||
this.template.fields.splice(fieldIndex, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.drawField = null
|
this.drawField = null
|
||||||
this.drawOption = null
|
this.drawOption = null
|
||||||
|
this.showDrawField = false
|
||||||
|
|
||||||
|
if (!this.withSelectedFieldType) {
|
||||||
|
this.drawFieldType = ''
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onKeyUp (e) {
|
onKeyUp (e) {
|
||||||
if (e.code === 'Escape') {
|
if (e.code === 'Escape') {
|
||||||
@@ -712,6 +749,27 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setDefaultAreaSize (area, type) {
|
||||||
|
const documentRef = this.documentRefs.find((e) => e.document.uuid === area.attachment_uuid)
|
||||||
|
const pageMask = documentRef.pageRefs[area.page].$refs.mask
|
||||||
|
|
||||||
|
if (type === 'checkbox') {
|
||||||
|
area.w = pageMask.clientWidth / 30 / pageMask.clientWidth
|
||||||
|
area.h = (pageMask.clientWidth / 30 / pageMask.clientWidth) * (pageMask.clientWidth / pageMask.clientHeight)
|
||||||
|
} else if (type === 'image') {
|
||||||
|
area.w = pageMask.clientWidth / 5 / pageMask.clientWidth
|
||||||
|
area.h = (pageMask.clientWidth / 5 / pageMask.clientWidth) * (pageMask.clientWidth / pageMask.clientHeight)
|
||||||
|
} else if (type === 'signature' || type === 'stamp') {
|
||||||
|
area.w = pageMask.clientWidth / 5 / pageMask.clientWidth
|
||||||
|
area.h = (pageMask.clientWidth / 5 / pageMask.clientWidth) * (pageMask.clientWidth / pageMask.clientHeight) / 2
|
||||||
|
} else if (type === 'initials') {
|
||||||
|
area.w = pageMask.clientWidth / 10 / pageMask.clientWidth
|
||||||
|
area.h = (pageMask.clientWidth / 35 / pageMask.clientWidth)
|
||||||
|
} else {
|
||||||
|
area.w = pageMask.clientWidth / 5 / pageMask.clientWidth
|
||||||
|
area.h = (pageMask.clientWidth / 35 / pageMask.clientWidth)
|
||||||
|
}
|
||||||
|
},
|
||||||
onDraw (area) {
|
onDraw (area) {
|
||||||
if (this.drawField) {
|
if (this.drawField) {
|
||||||
if (this.drawOption) {
|
if (this.drawOption) {
|
||||||
@@ -734,25 +792,7 @@ export default {
|
|||||||
area.w = previousArea.w
|
area.w = previousArea.w
|
||||||
area.h = previousArea.h
|
area.h = previousArea.h
|
||||||
} else {
|
} else {
|
||||||
const documentRef = this.documentRefs.find((e) => e.document.uuid === area.attachment_uuid)
|
this.setDefaultAreaSize(area, this.drawOption ? 'checkbox' : this.drawField?.type)
|
||||||
const pageMask = documentRef.pageRefs[area.page].$refs.mask
|
|
||||||
|
|
||||||
if (this.drawField.type === 'checkbox' || this.drawOption) {
|
|
||||||
area.w = pageMask.clientWidth / 30 / pageMask.clientWidth
|
|
||||||
area.h = (pageMask.clientWidth / 30 / pageMask.clientWidth) * (pageMask.clientWidth / pageMask.clientHeight)
|
|
||||||
} else if (this.drawField.type === 'image') {
|
|
||||||
area.w = pageMask.clientWidth / 5 / pageMask.clientWidth
|
|
||||||
area.h = (pageMask.clientWidth / 5 / pageMask.clientWidth) * (pageMask.clientWidth / pageMask.clientHeight)
|
|
||||||
} else if (this.drawField.type === 'signature' || this.drawField.type === 'stamp') {
|
|
||||||
area.w = pageMask.clientWidth / 5 / pageMask.clientWidth
|
|
||||||
area.h = (pageMask.clientWidth / 5 / pageMask.clientWidth) * (pageMask.clientWidth / pageMask.clientHeight) / 2
|
|
||||||
} else if (this.drawField.type === 'initials') {
|
|
||||||
area.w = pageMask.clientWidth / 10 / pageMask.clientWidth
|
|
||||||
area.h = (pageMask.clientWidth / 35 / pageMask.clientWidth)
|
|
||||||
} else {
|
|
||||||
area.w = pageMask.clientWidth / 5 / pageMask.clientWidth
|
|
||||||
area.h = (pageMask.clientWidth / 35 / pageMask.clientWidth)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
area.x -= area.w / 2
|
area.x -= area.w / 2
|
||||||
@@ -787,13 +827,15 @@ export default {
|
|||||||
|
|
||||||
let type = (pageMask.clientWidth * area.w) < 35 ? 'checkbox' : 'text'
|
let type = (pageMask.clientWidth * area.w) < 35 ? 'checkbox' : 'text'
|
||||||
|
|
||||||
if (this.defaultDrawFieldType && this.defaultDrawFieldType !== 'text') {
|
if (this.drawFieldType) {
|
||||||
|
type = this.drawFieldType
|
||||||
|
} else if (this.defaultDrawFieldType && this.defaultDrawFieldType !== 'text') {
|
||||||
type = this.defaultDrawFieldType
|
type = this.defaultDrawFieldType
|
||||||
} else if (this.fieldTypes.length !== 0 && !this.fieldTypes.includes(type)) {
|
} else if (this.fieldTypes.length !== 0 && !this.fieldTypes.includes(type)) {
|
||||||
type = this.fieldTypes[0]
|
type = this.fieldTypes[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'checkbox') {
|
if (type === 'checkbox' && !this.drawFieldType) {
|
||||||
const previousField = [...this.template.fields].reverse().find((f) => f.type === type)
|
const previousField = [...this.template.fields].reverse().find((f) => f.type === type)
|
||||||
const previousArea = previousField?.areas?.[previousField.areas.length - 1]
|
const previousArea = previousField?.areas?.[previousField.areas.length - 1]
|
||||||
|
|
||||||
@@ -811,21 +853,22 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (area.w) {
|
if (this.drawFieldType && (area.w === 0 || area.h === 0)) {
|
||||||
const field = {
|
if (this.selectedField?.type === this.drawFieldType) {
|
||||||
name: '',
|
area.w = this.selectedAreaRef.value.w
|
||||||
uuid: v4(),
|
area.h = this.selectedAreaRef.value.h
|
||||||
required: type !== 'checkbox',
|
} else {
|
||||||
type,
|
this.setDefaultAreaSize(area, this.drawFieldType)
|
||||||
submitter_uuid: this.selectedSubmitter.uuid,
|
|
||||||
areas: [area]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.template.fields.push(field)
|
area.x -= area.w / 2
|
||||||
|
area.y -= area.h / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if (area.w) {
|
||||||
|
this.addField(type, area)
|
||||||
|
|
||||||
this.selectedAreaRef.value = area
|
this.selectedAreaRef.value = area
|
||||||
|
|
||||||
this.save()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
:default-fields="defaultFields"
|
:default-fields="defaultFields"
|
||||||
:default-submitters="defaultSubmitters"
|
:default-submitters="defaultSubmitters"
|
||||||
:draw-field="drawField"
|
:draw-field="drawField"
|
||||||
|
:draw-field-type="drawFieldType"
|
||||||
:selected-submitter="selectedSubmitter"
|
:selected-submitter="selectedSubmitter"
|
||||||
:image="image"
|
:image="image"
|
||||||
@drop-field="$emit('drop-field', {...$event, attachment_uuid: document.uuid })"
|
@drop-field="$emit('drop-field', {...$event, attachment_uuid: document.uuid })"
|
||||||
@@ -43,6 +44,11 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: () => []
|
default: () => []
|
||||||
},
|
},
|
||||||
|
drawFieldType: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
defaultSubmitters: {
|
defaultSubmitters: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: false,
|
required: false,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
@drop.prevent="onDropFiles"
|
@drop.prevent="onDropFiles"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="w-full relative bg-base-200 hover:bg-base-200/70 rounded-md border border-base-content border-dashed"
|
class="w-full relative hover:bg-base-200/30 rounded-md border border-2 border-base-content/10 border-dashed"
|
||||||
:for="inputId"
|
:for="inputId"
|
||||||
:class="{ 'opacity-50': isLoading || isProcessing }"
|
:class="{ 'opacity-50': isLoading || isProcessing }"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -105,14 +105,18 @@
|
|||||||
<button
|
<button
|
||||||
v-if="(fieldTypes.length === 0 || fieldTypes.includes(type)) && (withPhone || type != 'phone') && (withPayment || type != 'payment')"
|
v-if="(fieldTypes.length === 0 || fieldTypes.includes(type)) && (withPhone || type != 'phone') && (withPayment || type != 'payment')"
|
||||||
draggable="true"
|
draggable="true"
|
||||||
class="field-type-button group flex items-center justify-center border border-dashed border-base-300 hover:border-base-content/20 w-full rounded relative"
|
class="field-type-button group flex items-center justify-center border border-dashed w-full rounded relative"
|
||||||
:style="{ backgroundColor: backgroundColor }"
|
:style="{ backgroundColor: backgroundColor }"
|
||||||
|
:class="drawFieldType === type ? 'border-base-content/40' : 'border-base-300 hover:border-base-content/20'"
|
||||||
@dragstart="onDragstart({ type: type })"
|
@dragstart="onDragstart({ type: type })"
|
||||||
@dragend="$emit('drag-end')"
|
@dragend="$emit('drag-end')"
|
||||||
@click="addField(type)"
|
@click="['file', 'payment'].includes(type) ? $emit('add-field', type) : $emit('set-draw-type', type)"
|
||||||
>
|
>
|
||||||
<div class="flex items-console group-hover:bg-base-200/50 transition-all cursor-grab h-full absolute left-0">
|
<div
|
||||||
<IconDrag class=" my-auto" />
|
class="flex items-console transition-all cursor-grab h-full absolute left-0"
|
||||||
|
:class="drawFieldType === type ? 'bg-base-200/50' : 'group-hover:bg-base-200/50'"
|
||||||
|
>
|
||||||
|
<IconDrag class="my-auto" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center flex-col px-2 py-2">
|
<div class="flex items-center flex-col px-2 py-2">
|
||||||
<component :is="icon" />
|
<component :is="icon" />
|
||||||
@@ -170,10 +174,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Field from './field'
|
import Field from './field'
|
||||||
import { v4 } from 'uuid'
|
|
||||||
import FieldType from './field_type'
|
import FieldType from './field_type'
|
||||||
import FieldSubmitter from './field_submitter'
|
import FieldSubmitter from './field_submitter'
|
||||||
import { IconLock } from '@tabler/icons-vue'
|
import { IconLock, IconCirclePlus } from '@tabler/icons-vue'
|
||||||
import IconDrag from './icon_drag'
|
import IconDrag from './icon_drag'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -181,6 +184,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
Field,
|
Field,
|
||||||
FieldType,
|
FieldType,
|
||||||
|
IconCirclePlus,
|
||||||
FieldSubmitter,
|
FieldSubmitter,
|
||||||
IconDrag,
|
IconDrag,
|
||||||
IconLock
|
IconLock
|
||||||
@@ -211,6 +215,11 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
|
drawFieldType: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
defaultSubmitters: {
|
defaultSubmitters: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -235,7 +244,7 @@ export default {
|
|||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['set-draw', 'set-drag', 'drag-end', 'scroll-to-area', 'change-submitter'],
|
emits: ['add-field', 'set-draw', 'set-draw-type', 'set-drag', 'drag-end', 'scroll-to-area', 'change-submitter'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
defaultFieldsSearch: ''
|
defaultFieldsSearch: ''
|
||||||
@@ -332,38 +341,6 @@ export default {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.save()
|
|
||||||
},
|
|
||||||
addField (type, area = null) {
|
|
||||||
const field = {
|
|
||||||
name: '',
|
|
||||||
uuid: v4(),
|
|
||||||
required: type !== 'checkbox',
|
|
||||||
areas: [],
|
|
||||||
submitter_uuid: this.selectedSubmitter.uuid,
|
|
||||||
type
|
|
||||||
}
|
|
||||||
|
|
||||||
if (['select', 'multiple', 'radio'].includes(type)) {
|
|
||||||
field.options = [{ value: '', uuid: v4() }]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'stamp') {
|
|
||||||
field.readonly = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'date') {
|
|
||||||
field.preferences = {
|
|
||||||
format: Intl.DateTimeFormat().resolvedOptions().locale.endsWith('-US') ? 'MM/DD/YYYY' : 'DD/MM/YYYY'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fields.push(field)
|
|
||||||
|
|
||||||
if (!['payment', 'file'].includes(type)) {
|
|
||||||
this.$emit('set-draw', { field })
|
|
||||||
}
|
|
||||||
|
|
||||||
this.save()
|
this.save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,11 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: () => []
|
default: () => []
|
||||||
},
|
},
|
||||||
|
drawFieldType: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
allowDraw: {
|
allowDraw: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -123,7 +128,9 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
defaultFieldType () {
|
defaultFieldType () {
|
||||||
if (this.defaultDrawFieldType && this.defaultDrawFieldType !== 'text') {
|
if (this.drawFieldType) {
|
||||||
|
return this.drawFieldType
|
||||||
|
} else if (this.defaultDrawFieldType && this.defaultDrawFieldType !== 'text') {
|
||||||
return this.defaultDrawFieldType
|
return this.defaultDrawFieldType
|
||||||
} else if (this.fieldTypes.length !== 0 && !this.fieldTypes.includes('text')) {
|
} else if (this.fieldTypes.length !== 0 && !this.fieldTypes.includes('text')) {
|
||||||
return this.fieldTypes[0]
|
return this.fieldTypes[0]
|
||||||
|
|||||||
Reference in New Issue
Block a user