fix: add/delete column in kanban
This commit is contained in:
parent
57a954eb9a
commit
98cc43b683
@ -332,7 +332,8 @@ def get_data(
|
|||||||
|
|
||||||
for kc in kanban_columns:
|
for kc in kanban_columns:
|
||||||
column_filters = { column_field: kc.get('name') }
|
column_filters = { column_field: kc.get('name') }
|
||||||
if column_field in filters and filters.get(column_field) != kc.name:
|
order = kc.get("order")
|
||||||
|
if column_field in filters and filters.get(column_field) != kc.name or kc.get('delete'):
|
||||||
column_data = []
|
column_data = []
|
||||||
else:
|
else:
|
||||||
column_filters.update(filters.copy())
|
column_filters.update(filters.copy())
|
||||||
@ -341,7 +342,6 @@ def get_data(
|
|||||||
if kc.get("page_length"):
|
if kc.get("page_length"):
|
||||||
page_length = kc.get("page_length")
|
page_length = kc.get("page_length")
|
||||||
|
|
||||||
order = kc.get("order")
|
|
||||||
if order:
|
if order:
|
||||||
column_data = get_records_based_on_order(doctype, rows, column_filters, page_length, order)
|
column_data = get_records_based_on_order(doctype, rows, column_filters, page_length, order)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -1,145 +1,169 @@
|
|||||||
<template>
|
<template>
|
||||||
<Draggable
|
<div class="flex overflow-x-auto">
|
||||||
v-if="columns"
|
<Draggable
|
||||||
:list="columns"
|
v-if="columns"
|
||||||
item-key="column"
|
:list="columns"
|
||||||
@end="updateColumn"
|
item-key="column"
|
||||||
class="flex sm:mx-2.5 mx-2 pb-3.5 overflow-x-auto"
|
@end="updateColumn"
|
||||||
>
|
class="flex sm:mx-2.5 mx-2 pb-3.5"
|
||||||
<template #item="{ element: column }">
|
>
|
||||||
<div
|
<template #item="{ element: column }">
|
||||||
v-if="!column.delete"
|
<div
|
||||||
class="flex flex-col gap-2.5 min-w-72 w-72 hover:bg-gray-100 rounded-lg p-2.5"
|
v-if="!column.column.delete"
|
||||||
>
|
class="flex flex-col gap-2.5 min-w-72 w-72 hover:bg-gray-100 rounded-lg p-2.5"
|
||||||
<div class="flex gap-2 items-center group justify-between">
|
>
|
||||||
<div class="flex items-center text-base">
|
<div class="flex gap-2 items-center group justify-between">
|
||||||
<NestedPopover>
|
<div class="flex items-center text-base">
|
||||||
<template #target>
|
<NestedPopover>
|
||||||
<Button variant="ghost" size="sm" class="hover:!bg-gray-100">
|
<template #target>
|
||||||
<IndicatorIcon
|
<Button variant="ghost" size="sm" class="hover:!bg-gray-100">
|
||||||
:class="colorClasses(column.column.color, true)"
|
<IndicatorIcon
|
||||||
/>
|
:class="colorClasses(column.column.color, true)"
|
||||||
</Button>
|
|
||||||
</template>
|
|
||||||
<template #body="{ close }">
|
|
||||||
<div
|
|
||||||
class="flex flex-col gap-3 px-3 py-2.5 rounded-lg border border-gray-100 bg-white shadow-xl"
|
|
||||||
>
|
|
||||||
<div class="flex gap-1">
|
|
||||||
<Button
|
|
||||||
:class="colorClasses(color)"
|
|
||||||
variant="ghost"
|
|
||||||
v-for="color in colors"
|
|
||||||
:key="color"
|
|
||||||
@click="() => (column.column.color = color)"
|
|
||||||
>
|
|
||||||
<IndicatorIcon />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-row-reverse">
|
|
||||||
<Button
|
|
||||||
variant="solid"
|
|
||||||
:label="__('Apply')"
|
|
||||||
@click="updateColumn"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</Button>
|
||||||
</div>
|
</template>
|
||||||
</template>
|
<template #body="{ close }">
|
||||||
</NestedPopover>
|
<div
|
||||||
<div>{{ column.column.name }}</div>
|
class="flex flex-col gap-3 px-3 py-2.5 rounded-lg border border-gray-100 bg-white shadow-xl"
|
||||||
</div>
|
>
|
||||||
<div class="flex">
|
<div class="flex gap-1">
|
||||||
<Dropdown :options="actions(column)">
|
<Button
|
||||||
<template #default>
|
:class="colorClasses(color)"
|
||||||
<Button
|
variant="ghost"
|
||||||
class="hidden group-hover:flex"
|
v-for="color in colors"
|
||||||
icon="more-horizontal"
|
:key="color"
|
||||||
variant="ghost"
|
@click="() => (column.column.color = color)"
|
||||||
/>
|
>
|
||||||
</template>
|
<IndicatorIcon />
|
||||||
</Dropdown>
|
</Button>
|
||||||
<Button
|
</div>
|
||||||
icon="plus"
|
<div class="flex flex-row-reverse">
|
||||||
variant="ghost"
|
<Button
|
||||||
@click="options.onNewClick(column)"
|
variant="solid"
|
||||||
/>
|
:label="__('Apply')"
|
||||||
</div>
|
@click="updateColumn"
|
||||||
</div>
|
/>
|
||||||
<div class="overflow-y-auto flex flex-col gap-2 h-full">
|
|
||||||
<Draggable
|
|
||||||
:list="column.data"
|
|
||||||
group="fields"
|
|
||||||
item-key="name"
|
|
||||||
class="flex flex-col gap-3.5 flex-1"
|
|
||||||
@end="updateColumn"
|
|
||||||
:data-column="column.column.name"
|
|
||||||
>
|
|
||||||
<template #item="{ element: fields }">
|
|
||||||
<component
|
|
||||||
:is="options.getRoute ? 'router-link' : 'div'"
|
|
||||||
class="pt-3 px-3.5 pb-2.5 rounded-lg border bg-white text-base flex flex-col"
|
|
||||||
:data-name="fields.name"
|
|
||||||
v-bind="{
|
|
||||||
to: options.getRoute ? options.getRoute(fields) : undefined,
|
|
||||||
onClick: options.onClick
|
|
||||||
? () => options.onClick(fields)
|
|
||||||
: undefined,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<slot
|
|
||||||
name="title"
|
|
||||||
v-bind="{ fields, titleField, itemName: fields.name }"
|
|
||||||
>
|
|
||||||
<div class="h-5 flex items-center">
|
|
||||||
<div v-if="fields[titleField]">
|
|
||||||
{{ fields[titleField] }}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="text-gray-500" v-else>{{ __('No Title') }}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</slot>
|
</template>
|
||||||
<div class="border-b h-px my-2.5" />
|
</NestedPopover>
|
||||||
|
<div>{{ column.column.name }}</div>
|
||||||
<div class="flex flex-col gap-3.5">
|
</div>
|
||||||
<template v-for="value in column.fields" :key="value">
|
<div class="flex">
|
||||||
<slot
|
<Dropdown :options="actions(column)">
|
||||||
name="fields"
|
<template #default>
|
||||||
v-bind="{
|
<Button
|
||||||
fields,
|
class="hidden group-hover:flex"
|
||||||
fieldName: value,
|
icon="more-horizontal"
|
||||||
itemName: fields.name,
|
variant="ghost"
|
||||||
}"
|
/>
|
||||||
>
|
</template>
|
||||||
<div v-if="fields[value]" class="truncate">
|
</Dropdown>
|
||||||
{{ fields[value] }}
|
<Button
|
||||||
|
icon="plus"
|
||||||
|
variant="ghost"
|
||||||
|
@click="options.onNewClick(column)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-y-auto flex flex-col gap-2 h-full">
|
||||||
|
<Draggable
|
||||||
|
:list="column.data"
|
||||||
|
group="fields"
|
||||||
|
item-key="name"
|
||||||
|
class="flex flex-col gap-3.5 flex-1"
|
||||||
|
@end="updateColumn"
|
||||||
|
:data-column="column.column.name"
|
||||||
|
>
|
||||||
|
<template #item="{ element: fields }">
|
||||||
|
<component
|
||||||
|
:is="options.getRoute ? 'router-link' : 'div'"
|
||||||
|
class="pt-3 px-3.5 pb-2.5 rounded-lg border bg-white text-base flex flex-col"
|
||||||
|
:data-name="fields.name"
|
||||||
|
v-bind="{
|
||||||
|
to: options.getRoute ? options.getRoute(fields) : undefined,
|
||||||
|
onClick: options.onClick
|
||||||
|
? () => options.onClick(fields)
|
||||||
|
: undefined,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<slot
|
||||||
|
name="title"
|
||||||
|
v-bind="{ fields, titleField, itemName: fields.name }"
|
||||||
|
>
|
||||||
|
<div class="h-5 flex items-center">
|
||||||
|
<div v-if="fields[titleField]">
|
||||||
|
{{ fields[titleField] }}
|
||||||
</div>
|
</div>
|
||||||
</slot>
|
<div class="text-gray-500" v-else>
|
||||||
</template>
|
{{ __('No Title') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="border-b h-px mt-2.5 mb-2" />
|
</div>
|
||||||
<slot name="actions" v-bind="{ itemName: fields.name }">
|
</slot>
|
||||||
<div class="flex gap-2 items-center justify-between">
|
<div class="border-b h-px my-2.5" />
|
||||||
<div></div>
|
|
||||||
<Button icon="plus" variant="ghost" @click.stop.prevent />
|
<div class="flex flex-col gap-3.5">
|
||||||
|
<template v-for="value in column.fields" :key="value">
|
||||||
|
<slot
|
||||||
|
name="fields"
|
||||||
|
v-bind="{
|
||||||
|
fields,
|
||||||
|
fieldName: value,
|
||||||
|
itemName: fields.name,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div v-if="fields[value]" class="truncate">
|
||||||
|
{{ fields[value] }}
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</slot>
|
<div class="border-b h-px mt-2.5 mb-2" />
|
||||||
</component>
|
<slot name="actions" v-bind="{ itemName: fields.name }">
|
||||||
</template>
|
<div class="flex gap-2 items-center justify-between">
|
||||||
</Draggable>
|
<div></div>
|
||||||
<div
|
<Button icon="plus" variant="ghost" @click.stop.prevent />
|
||||||
v-if="column.column.count < column.column.all_count"
|
</div>
|
||||||
class="flex items-center justify-center"
|
</slot>
|
||||||
>
|
</component>
|
||||||
<Button
|
</template>
|
||||||
:label="__('Load More')"
|
</Draggable>
|
||||||
@click="emit('loadMore', column.column.name)"
|
<div
|
||||||
/>
|
v-if="column.column.count < column.column.all_count"
|
||||||
|
class="flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
:label="__('Load More')"
|
||||||
|
@click="emit('loadMore', column.column.name)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</template>
|
</Draggable>
|
||||||
</Draggable>
|
<div v-if="deletedColumns.length" class="shrink-0 min-w-64">
|
||||||
|
<Autocomplete
|
||||||
|
value=""
|
||||||
|
:options="deletedColumns"
|
||||||
|
@change="(e) => addColumn(e)"
|
||||||
|
>
|
||||||
|
<template #target="{ togglePopover }">
|
||||||
|
<Button
|
||||||
|
class="w-full mt-2.5 mb-1 mr-5"
|
||||||
|
@click="togglePopover()"
|
||||||
|
:label="__('Add Column')"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<FeatherIcon name="plus" class="h-4" />
|
||||||
|
</template>
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
</Autocomplete>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import Autocomplete from '@/components/frappe-ui/Autocomplete.vue'
|
||||||
import NestedPopover from '@/components/NestedPopover.vue'
|
import NestedPopover from '@/components/NestedPopover.vue'
|
||||||
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
|
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
|
||||||
import Draggable from 'vuedraggable'
|
import Draggable from 'vuedraggable'
|
||||||
@ -179,6 +203,14 @@ const columns = computed(() => {
|
|||||||
return _columns
|
return _columns
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const deletedColumns = computed(() => {
|
||||||
|
return columns.value
|
||||||
|
.filter((col) => col.column['delete'])
|
||||||
|
.map((col) => {
|
||||||
|
return { label: col.column.name, value: col.column.name }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
function actions(column) {
|
function actions(column) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -189,7 +221,7 @@ function actions(column) {
|
|||||||
label: __('Delete'),
|
label: __('Delete'),
|
||||||
icon: 'trash-2',
|
icon: 'trash-2',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
column['delete'] = true
|
column.column['delete'] = true
|
||||||
updateColumn()
|
updateColumn()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -198,6 +230,12 @@ function actions(column) {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addColumn(e) {
|
||||||
|
let column = columns.value.find((col) => col.column.name == e.value)
|
||||||
|
column.column['delete'] = false
|
||||||
|
updateColumn()
|
||||||
|
}
|
||||||
|
|
||||||
function updateColumn(d) {
|
function updateColumn(d) {
|
||||||
let toColumn = d?.to?.dataset.column
|
let toColumn = d?.to?.dataset.column
|
||||||
let fromColumn = d?.from?.dataset.column
|
let fromColumn = d?.from?.dataset.column
|
||||||
@ -205,7 +243,6 @@ function updateColumn(d) {
|
|||||||
|
|
||||||
let _columns = []
|
let _columns = []
|
||||||
columns.value.forEach((col) => {
|
columns.value.forEach((col) => {
|
||||||
if (col.delete) return
|
|
||||||
col.column['order'] = col.data.map((d) => d.name)
|
col.column['order'] = col.data.map((d) => d.name)
|
||||||
if (col.column.page_length) {
|
if (col.column.page_length) {
|
||||||
delete col.column.page_length
|
delete col.column.page_length
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user