Files
docuseal/app/javascript/template_builder/field_submitter.vue
T

371 lines
10 KiB
Vue
Raw Normal View History

2023-06-07 01:16:43 +03:00
<template>
2023-12-31 17:23:27 +02:00
<div
v-if="mobileView"
@mouseenter="renderDropdown = true"
@touchstart="renderDropdown = true"
>
2023-11-06 20:49:44 +02:00
<div class="flex space-x-2 items-end">
<div class="group/contenteditable-container bg-base-100 rounded-md p-2 border border-base-300 w-full flex justify-between items-end">
<div class="flex items-center space-x-2">
<span
class="w-3 h-3 flex-shrink-0 rounded-full"
:class="colors[submitters.indexOf(selectedSubmitter)]"
/>
<Contenteditable
v-model="selectedSubmitter.name"
class="cursor-text"
:icon-inline="true"
:editable="editable"
:select-on-edit-click="true"
:icon-width="18"
@update:model-value="$emit('name-change', selectedSubmitter)"
/>
</div>
</div>
<div class="dropdown dropdown-top dropdown-end">
<label
tabindex="0"
class="bg-base-100 cursor-pointer rounded-md p-2 border border-base-300 w-full flex justify-center"
>
<IconChevronUp
width="24"
height="24"
/>
</label>
<ul
2023-12-31 17:23:27 +02:00
v-if="editable && renderDropdown"
2023-11-06 20:49:44 +02:00
tabindex="0"
class="rounded-md min-w-max mb-2"
:class="menuClasses"
2024-04-23 01:57:45 +03:00
:style="menuStyle"
2023-11-06 20:49:44 +02:00
@click="closeDropdown"
>
<li
v-for="(submitter, index) in submitters"
:key="submitter.uuid"
>
<a
href="#"
class="flex px-2 group justify-between items-center"
:class="{ 'active': submitter === selectedSubmitter }"
@click.prevent="selectSubmitter(submitter)"
>
<span class="py-1 flex items-center">
<span
class="rounded-full w-3 h-3 ml-1 mr-3"
:class="colors[index]"
/>
<span>
{{ submitter.name }}
</span>
</span>
<button
v-if="submitters.length > 1 && editable"
class="px-2"
2024-01-19 10:15:21 +02:00
@click.prevent.stop="remove(submitter)"
2023-11-06 20:49:44 +02:00
>
<IconTrashX :width="18" />
</button>
</a>
</li>
2024-02-10 01:19:02 +02:00
<li v-if="submitters.length < names.length && editable">
2023-11-06 20:49:44 +02:00
<a
href="#"
class="flex px-2"
@click.prevent="addSubmitter"
>
<IconUserPlus
:width="20"
:stroke-width="1.6"
/>
<span class="py-1">
2024-01-04 01:05:36 +02:00
{{ t('add') }} {{ names[submitters.length] }}
2023-11-06 20:49:44 +02:00
</span>
</a>
</li>
</ul>
</div>
</div>
</div>
<div
v-else
class="dropdown"
2023-12-31 17:23:27 +02:00
@mouseenter="renderDropdown = true"
@touchstart="renderDropdown = true"
2023-11-06 20:49:44 +02:00
>
2023-06-07 01:16:43 +03:00
<label
v-if="compact"
tabindex="0"
2024-04-06 21:44:44 +03:00
:title="selectedSubmitter?.name"
2023-06-30 23:22:57 +03:00
class="cursor-pointer text-base-100 flex h-full items-center justify-center"
2023-06-07 01:16:43 +03:00
>
<button
class="mx-1 w-3 h-3 rounded-full"
:class="colors[submitters.indexOf(selectedSubmitter)]"
/>
</label>
<label
v-else
2024-01-06 22:25:13 +02:00
ref="label"
2023-06-07 01:16:43 +03:00
tabindex="0"
2023-11-21 23:08:59 +02:00
class="group cursor-pointer group/contenteditable-container rounded-md p-2 border border-base-300 hover:border-content w-full flex justify-between"
2023-06-07 01:16:43 +03:00
>
<div class="flex items-center space-x-2">
<span
class="w-3 h-3 rounded-full"
:class="colors[submitters.indexOf(selectedSubmitter)]"
/>
<Contenteditable
v-model="selectedSubmitter.name"
2023-06-08 00:20:42 +03:00
class="cursor-text"
2023-06-07 01:16:43 +03:00
:icon-inline="true"
2023-11-04 01:19:32 +02:00
:editable="editable"
2023-09-23 18:23:34 +03:00
:select-on-edit-click="true"
2023-06-07 01:16:43 +03:00
:icon-width="18"
2023-06-24 16:17:07 +03:00
@update:model-value="$emit('name-change', selectedSubmitter)"
2023-06-07 01:16:43 +03:00
/>
</div>
2023-11-21 23:08:59 +02:00
<span class="flex items-center transition-all duration-75 group-hover:border border-base-content/20 border-dashed w-6 h-6 flex justify-center items-center rounded">
2024-01-23 23:20:19 +02:00
<component
:is="editable ? 'IconPlus' : 'IconChevronDown'"
2023-09-05 20:50:21 +03:00
width="18"
height="18"
/>
2023-06-07 01:16:43 +03:00
</span>
</label>
<ul
2023-12-31 17:23:27 +02:00
v-if="(editable || !compact) && renderDropdown"
2023-06-07 01:16:43 +03:00
tabindex="0"
:class="menuClasses"
2024-04-23 01:57:45 +03:00
:style="menuStyle"
2023-06-07 01:16:43 +03:00
@click="closeDropdown"
>
<li
v-for="(submitter, index) in submitters"
:key="submitter.uuid"
>
<a
href="#"
class="flex px-2 group justify-between items-center"
2024-02-10 01:19:02 +02:00
:class="{ 'active': submitter === selectedSubmitter, 'py-0.5': submitters.length > 8 }"
2023-06-07 01:16:43 +03:00
@click.prevent="selectSubmitter(submitter)"
>
<span class="py-1 flex items-center">
<span
class="rounded-full w-3 h-3 ml-1 mr-3"
:class="colors[index]"
/>
<span>
{{ submitter.name }}
</span>
</span>
2024-01-06 22:25:13 +02:00
<div
2023-11-04 01:19:32 +02:00
v-if="!compact && submitters.length > 1 && editable"
2024-01-06 22:25:13 +02:00
class="flex"
2023-06-07 01:16:43 +03:00
>
2024-01-06 22:25:13 +02:00
<div class="flex-col pr-1 hidden group-hover:flex -mt-1 h-0">
<button
2024-02-19 23:52:47 +02:00
:title="t('up')"
2024-01-06 22:25:13 +02:00
class="relative w-2"
style="font-size: 10px; margin-bottom: -4px"
2024-01-19 10:15:21 +02:00
@click.prevent.stop="[move(submitter, -1), $refs.label.focus()] "
2024-01-06 22:25:13 +02:00
>
▲
</button>
<button
2024-02-19 23:52:47 +02:00
:title="t('down')"
2024-01-06 22:25:13 +02:00
class="relative w-2"
style="font-size: 10px; margin-top: -4px"
2024-01-19 10:15:21 +02:00
@click.prevent.stop="[move(submitter, 1), $refs.label.focus()] "
2024-01-06 22:25:13 +02:00
>
▼
</button>
</div>
<button
v-if="!compact && submitters.length > 1 && editable"
class="hidden group-hover:block px-2"
2024-01-19 10:15:21 +02:00
@click.prevent.stop="remove(submitter)"
2024-01-06 22:25:13 +02:00
>
<IconTrashX :width="18" />
</button>
</div>
2023-06-07 01:16:43 +03:00
</a>
</li>
2024-02-10 01:19:02 +02:00
<li v-if="submitters.length < names.length && editable && allowAddNew">
2023-06-07 01:16:43 +03:00
<a
href="#"
class="flex px-2"
@click.prevent="addSubmitter"
>
<IconUserPlus
:width="20"
:stroke-width="1.6"
/>
<span class="py-1">
2024-01-04 01:05:36 +02:00
{{ t('add') }} {{ names[submitters.length] }}
2023-06-07 01:16:43 +03:00
</span>
</a>
</li>
</ul>
</div>
</template>
<script>
2024-01-23 23:20:19 +02:00
import { IconUserPlus, IconTrashX, IconPlus, IconChevronUp, IconChevronDown } from '@tabler/icons-vue'
2023-06-07 01:16:43 +03:00
import Contenteditable from './contenteditable'
import { v4 } from 'uuid'
export default {
name: 'FieldSubmitter',
components: {
IconUserPlus,
2024-01-23 23:20:19 +02:00
IconChevronDown,
2023-06-07 01:16:43 +03:00
Contenteditable,
2023-09-05 20:50:21 +03:00
IconPlus,
2023-11-06 20:49:44 +02:00
IconTrashX,
IconChevronUp
2023-06-07 01:16:43 +03:00
},
2024-01-06 22:25:13 +02:00
inject: ['t', 'save'],
2023-06-07 01:16:43 +03:00
props: {
submitters: {
type: Array,
required: true
},
2023-11-04 01:19:32 +02:00
editable: {
type: Boolean,
required: false,
default: true
},
2023-06-07 01:16:43 +03:00
compact: {
type: Boolean,
required: false,
default: false
},
2023-11-06 20:49:44 +02:00
mobileView: {
type: Boolean,
required: false,
default: false
},
2024-01-23 23:20:19 +02:00
allowAddNew: {
type: Boolean,
required: false,
default: true
},
2023-06-07 01:16:43 +03:00
modelValue: {
type: String,
required: true
},
2024-04-23 01:57:45 +03:00
menuStyle: {
type: Object,
required: false,
default: () => ({})
},
2023-06-07 01:16:43 +03:00
menuClasses: {
type: String,
required: false,
2024-04-23 01:57:45 +03:00
default: 'dropdown-content menu p-2 shadow rounded-box w-full z-10'
2023-06-07 01:16:43 +03:00
}
},
2023-06-24 16:17:07 +03:00
emits: ['update:model-value', 'remove', 'new-submitter', 'name-change'],
2023-12-31 17:23:27 +02:00
data () {
return {
renderDropdown: false
}
},
2023-06-07 01:16:43 +03:00
computed: {
colors () {
return [
'bg-red-500',
'bg-sky-500',
'bg-emerald-500',
'bg-yellow-300',
'bg-purple-600',
'bg-pink-500',
'bg-cyan-500',
'bg-orange-500',
'bg-lime-500',
2024-02-08 11:54:54 +02:00
'bg-indigo-500',
'bg-red-500',
'bg-sky-500',
'bg-emerald-500',
'bg-yellow-300',
'bg-purple-600',
'bg-pink-500',
'bg-cyan-500',
2024-02-10 01:19:02 +02:00
'bg-orange-500',
'bg-lime-500',
'bg-indigo-500'
2023-06-07 01:16:43 +03:00
]
},
2023-06-08 00:20:42 +03:00
names () {
return [
2024-01-04 01:05:36 +02:00
this.t('first_party'),
this.t('second_party'),
this.t('third_party'),
this.t('fourth_party'),
this.t('fifth_party'),
this.t('sixth_party'),
this.t('seventh_party'),
this.t('eighth_party'),
this.t('ninth_party'),
2024-02-08 11:54:54 +02:00
this.t('tenth_party'),
this.t('eleventh_party'),
this.t('twelfth_party'),
this.t('thirteenth_party'),
this.t('fourteenth_party'),
this.t('fifteenth_party'),
this.t('sixteenth_party'),
this.t('seventeenth_party'),
2024-02-10 01:19:02 +02:00
this.t('eighteenth_party'),
this.t('nineteenth_party'),
this.t('twentieth_party')
2023-06-08 00:20:42 +03:00
]
},
2023-06-07 01:16:43 +03:00
selectedSubmitter () {
return this.submitters.find((e) => e.uuid === this.modelValue)
}
},
methods: {
selectSubmitter (submitter) {
this.$emit('update:model-value', submitter.uuid)
},
remove (submitter) {
2024-10-07 14:58:28 +03:00
if (window.confirm(this.t('are_you_sure_'))) {
2023-06-07 01:16:43 +03:00
this.$emit('remove', submitter)
}
},
2024-01-06 22:25:13 +02:00
move (submitter, direction) {
const currentIndex = this.submitters.indexOf(submitter)
this.submitters.splice(currentIndex, 1)
if (currentIndex + direction > this.submitters.length) {
this.submitters.unshift(submitter)
} else if (currentIndex + direction < 0) {
this.submitters.push(submitter)
} else {
this.submitters.splice(currentIndex + direction, 0, submitter)
}
this.selectSubmitter(submitter)
this.save()
},
2023-06-07 01:16:43 +03:00
addSubmitter () {
const newSubmitter = {
2023-06-08 00:20:42 +03:00
name: this.names[this.submitters.length],
2023-06-07 01:16:43 +03:00
uuid: v4()
}
this.submitters.push(newSubmitter)
this.$emit('update:model-value', newSubmitter.uuid)
2023-06-24 16:17:07 +03:00
this.$emit('new-submitter', newSubmitter)
2023-06-07 01:16:43 +03:00
},
closeDropdown () {
document.activeElement.blur()
}
}
}
</script>