crm/frontend/src/components/Kanban/KanbanSettings.vue
2024-12-29 18:45:50 +05:30

220 lines
5.8 KiB
Vue

<template>
<Button
:label="__('Kanban Settings')"
@click="showDialog = true"
v-bind="$attrs"
>
<template #prefix>
<KanbanIcon class="h-4" />
</template>
</Button>
<Dialog v-model="showDialog" :options="{ title: __('Kanban Settings') }">
<template #body-content>
<div>
<div class="text-base text-ink-gray-8 mb-2">
{{ __('Column Field') }}
</div>
<Autocomplete
v-if="columnFields"
value=""
:options="columnFields"
@change="(f) => (columnField = f)"
>
<template #target="{ togglePopover }">
<Button
class="w-full !justify-start"
@click="togglePopover()"
:label="columnField.label"
/>
</template>
</Autocomplete>
<div class="text-base text-ink-gray-8 mb-2 mt-4">
{{ __('Title Field') }}
</div>
<Autocomplete
v-if="fields.data"
value=""
:options="fields.data"
@change="(f) => (titleField = f)"
>
<template #target="{ togglePopover }">
<Button
class="w-full !justify-start"
@click="togglePopover()"
:label="titleField.label"
/>
</template>
</Autocomplete>
</div>
<div class="mt-4">
<div class="text-base text-ink-gray-8 mb-2">
{{ __('Fields Order') }}
</div>
<Draggable
:list="allFields"
@end="reorder"
group="fields"
item-key="name"
class="flex flex-col gap-1"
>
<template #item="{ element: field }">
<div
class="px-1 py-0.5 border border-outline-gray-modals rounded text-base text-ink-gray-8 flex items-center justify-between gap-2"
>
<div class="flex items-center gap-2">
<DragVerticalIcon class="h-3.5 cursor-grab" />
<div>{{ field.label }}</div>
</div>
<div>
<Button variant="ghost" icon="x" @click="removeField(field)" />
</div>
</div>
</template>
</Draggable>
<Autocomplete
v-if="fields.data"
value=""
:options="fields.data"
@change="(e) => addField(e)"
>
<template #target="{ togglePopover }">
<Button
class="w-full mt-2"
@click="togglePopover()"
:label="__('Add Field')"
>
<template #prefix>
<FeatherIcon name="plus" class="h-4" />
</template>
</Button>
</template>
<template #item-label="{ option }">
<div class="flex flex-col gap-1 text-ink-gray-9">
<div>{{ option.label }}</div>
<div class="text-ink-gray-4 text-sm">
{{ `${option.fieldname} - ${option.fieldtype}` }}
</div>
</div>
</template>
</Autocomplete>
</div>
</template>
<template #actions>
<Button
class="w-full"
variant="solid"
@click="apply"
:label="__('Apply')"
/>
</template>
</Dialog>
</template>
<script setup>
import DragVerticalIcon from '@/components/Icons/DragVerticalIcon.vue'
import KanbanIcon from '@/components/Icons/KanbanIcon.vue'
import Autocomplete from '@/components/frappe-ui/Autocomplete.vue'
import { Dialog, createResource } from 'frappe-ui'
import Draggable from 'vuedraggable'
import { ref, computed, nextTick } from 'vue'
const props = defineProps({
doctype: {
type: String,
required: true,
},
})
const emit = defineEmits(['update'])
const list = defineModel()
const showDialog = ref(false)
const columnField = computed({
get: () => {
let fieldname = list.value?.data?.column_field
if (!fieldname) return ''
return columnFields.value?.find((field) => field.fieldname === fieldname)
},
set: (val) => {
list.value.data.column_field = val.fieldname
},
})
const titleField = computed({
get: () => {
let fieldname = list.value?.data?.title_field
if (!fieldname) return ''
return fields.data?.find((field) => field.fieldname === fieldname)
},
set: (val) => {
list.value.data.title_field = val.fieldname
},
})
const columnFields = computed(() => {
return (
fields.data?.filter((field) =>
['Link', 'Select'].includes(field.fieldtype),
) || []
)
})
const fields = createResource({
url: 'crm.api.doc.get_fields_meta',
params: { doctype: props.doctype, as_array: true },
cache: ['kanban_fields', props.doctype],
auto: true,
})
const allFields = computed({
get: () => {
let rows = list.value?.data?.kanban_fields
if (!rows) return []
if (typeof rows === 'string') {
rows = JSON.parse(rows)
}
if (rows && fields.data) {
rows = rows.map((row) => {
return fields.data.find((field) => field.fieldname === row) || {}
})
}
return rows.filter((row) => row.label)
},
set: (val) => {
list.value.data.kanban_fields = val
},
})
function reorder() {
allFields.value = allFields.value.map((row) => row.fieldname)
}
function addField(field) {
if (!field) return
let rows = allFields.value || []
rows.push(field)
allFields.value = rows.map((row) => row.fieldname)
}
function removeField(field) {
let rows = allFields.value
rows = rows.filter((row) => row.fieldname !== field.fieldname)
allFields.value = rows.map((row) => row.fieldname)
}
function apply() {
nextTick(() => {
showDialog.value = false
emit('update', {
column_field: columnField.value.fieldname,
title_field: titleField.value.fieldname,
kanban_fields: allFields.value.map((row) => row.fieldname),
})
})
}
</script>