fix: removed old sort logic similar to filter and added new way to sort and save
This commit is contained in:
parent
fc4c144abe
commit
ffe942d80f
@ -3,29 +3,29 @@
|
|||||||
<template #target>
|
<template #target>
|
||||||
<Button label="Sort" ref="sortButtonRef">
|
<Button label="Sort" ref="sortButtonRef">
|
||||||
<template #prefix><SortIcon class="h-4" /></template>
|
<template #prefix><SortIcon class="h-4" /></template>
|
||||||
<template v-if="sortValues.length" #suffix>
|
<template v-if="sortValues?.size" #suffix>
|
||||||
<div
|
<div
|
||||||
class="flex justify-center items-center w-5 h-5 text-2xs font-medium pt-[1px] bg-gray-900 text-white rounded"
|
class="flex h-5 w-5 items-center justify-center rounded bg-gray-900 pt-[1px] text-2xs font-medium text-white"
|
||||||
>
|
>
|
||||||
{{ sortValues.length }}
|
{{ sortValues.size }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ close }">
|
<template #body="{ close }">
|
||||||
<div class="rounded-lg border border-gray-100 bg-white shadow-xl my-2">
|
<div class="my-2 rounded-lg border border-gray-100 bg-white shadow-xl">
|
||||||
<div class="p-2 min-w-[352px]">
|
<div class="min-w-[352px] p-2">
|
||||||
<div
|
<div
|
||||||
v-if="sortValues.length"
|
v-if="sortValues?.size"
|
||||||
id="sort-list"
|
id="sort-list"
|
||||||
class="flex flex-col gap-2 mb-3"
|
class="mb-3 flex flex-col gap-2"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(sort, i) in sortValues"
|
v-for="(sort, i) in sortValues"
|
||||||
:key="sort.fieldname"
|
:key="sort.fieldname"
|
||||||
class="flex items-center gap-2"
|
class="flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<div class="flex items-center justify-center h-7 w-7 handle">
|
<div class="handle flex h-7 w-7 items-center justify-center">
|
||||||
<DragIcon class="h-4 w-4 cursor-grab text-gray-600" />
|
<DragIcon class="h-4 w-4 cursor-grab text-gray-600" />
|
||||||
</div>
|
</div>
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
@ -38,11 +38,17 @@
|
|||||||
<FormControl
|
<FormControl
|
||||||
class="!w-32"
|
class="!w-32"
|
||||||
type="select"
|
type="select"
|
||||||
v-model="sort.direction"
|
:value="sort.direction"
|
||||||
:options="[
|
:options="[
|
||||||
{ label: 'Ascending', value: 'asc' },
|
{ label: 'Ascending', value: 'asc' },
|
||||||
{ label: 'Descending', value: 'desc' },
|
{ label: 'Descending', value: 'desc' },
|
||||||
]"
|
]"
|
||||||
|
@change="
|
||||||
|
(e) => {
|
||||||
|
sort.direction = e.target.value
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
"
|
||||||
placeholder="Sort by"
|
placeholder="Sort by"
|
||||||
/>
|
/>
|
||||||
<Button variant="ghost" icon="x" @click="removeSort(i)" />
|
<Button variant="ghost" icon="x" @click="removeSort(i)" />
|
||||||
@ -50,7 +56,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="text-gray-600 flex items-center text-sm px-3 h-7 mb-3"
|
class="mb-3 flex h-7 items-center px-3 text-sm text-gray-600"
|
||||||
>
|
>
|
||||||
Empty - Choose a field to sort by
|
Empty - Choose a field to sort by
|
||||||
</div>
|
</div>
|
||||||
@ -75,7 +81,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</Autocomplete>
|
</Autocomplete>
|
||||||
<Button
|
<Button
|
||||||
v-if="sortValues.length"
|
v-if="sortValues?.size"
|
||||||
class="!text-gray-600"
|
class="!text-gray-600"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
label="Clear Sort"
|
label="Clear Sort"
|
||||||
@ -93,7 +99,6 @@ import NestedPopover from '@/components/NestedPopover.vue'
|
|||||||
import SortIcon from '@/components/Icons/SortIcon.vue'
|
import SortIcon from '@/components/Icons/SortIcon.vue'
|
||||||
import DragIcon from '@/components/Icons/DragIcon.vue'
|
import DragIcon from '@/components/Icons/DragIcon.vue'
|
||||||
import { useSortable } from '@vueuse/integrations/useSortable'
|
import { useSortable } from '@vueuse/integrations/useSortable'
|
||||||
import { useOrderBy } from '@/composables/orderby'
|
|
||||||
import {
|
import {
|
||||||
FeatherIcon,
|
FeatherIcon,
|
||||||
Button,
|
Button,
|
||||||
@ -101,7 +106,7 @@ import {
|
|||||||
FormControl,
|
FormControl,
|
||||||
createResource,
|
createResource,
|
||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { computed, ref, watch } from 'vue'
|
import { computed, ref, nextTick } from 'vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
doctype: {
|
doctype: {
|
||||||
@ -110,10 +115,10 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const { get: getOrderBy, set: setOrderBy } = useOrderBy()
|
const emit = defineEmits(['update'])
|
||||||
|
const list = defineModel()
|
||||||
|
|
||||||
const sortButtonRef = ref(null)
|
const sortButtonRef = ref(null)
|
||||||
const sortValues = ref(initialOrderBy())
|
|
||||||
|
|
||||||
const sortOptions = createResource({
|
const sortOptions = createResource({
|
||||||
url: 'crm.api.doc.sort_options',
|
url: 'crm.api.doc.sort_options',
|
||||||
@ -123,75 +128,83 @@ const sortOptions = createResource({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const sortValues = computed({
|
||||||
|
get: () => {
|
||||||
|
if (!list.value?.data) return new Set()
|
||||||
|
let allSortValues = list.value?.params?.order_by
|
||||||
|
if (!allSortValues || !sortOptions.data) return new Set()
|
||||||
|
if (allSortValues.trim() === 'modified desc') return new Set()
|
||||||
|
allSortValues = allSortValues.split(', ').map((sortValue) => {
|
||||||
|
const [fieldname, direction] = sortValue.split(' ')
|
||||||
|
return { fieldname, direction }
|
||||||
|
})
|
||||||
|
return new Set(allSortValues)
|
||||||
|
},
|
||||||
|
set: (value) => {
|
||||||
|
list.value.params.order_by = convertToString(value)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
const options = computed(() => {
|
const options = computed(() => {
|
||||||
if (!sortOptions.data) return []
|
if (!sortOptions.data) return []
|
||||||
const selectedOptions = sortValues.value.map((sort) => sort.fieldname)
|
if (!sortValues.value.size) return sortOptions.data
|
||||||
|
const selectedOptions = [...sortValues.value].map((sort) => sort.fieldname)
|
||||||
|
restartSort()
|
||||||
return sortOptions.data.filter((option) => {
|
return sortOptions.data.filter((option) => {
|
||||||
return !selectedOptions.includes(option.value)
|
return !selectedOptions.includes(option.value)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
function initialOrderBy() {
|
|
||||||
const orderBy = getOrderBy()
|
|
||||||
if (!orderBy) return []
|
|
||||||
const sortOptions = orderBy.split(', ')
|
|
||||||
return sortOptions.map((sortOption) => {
|
|
||||||
const [fieldname, direction] = sortOption.split(' ')
|
|
||||||
return { fieldname, direction }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const sortSortable = useSortable('#sort-list', sortValues, {
|
const sortSortable = useSortable('#sort-list', sortValues, {
|
||||||
handle: '.handle',
|
handle: '.handle',
|
||||||
animation: 200,
|
animation: 200,
|
||||||
|
onEnd: () => apply(),
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(
|
|
||||||
() => sortValues.value,
|
|
||||||
(value) => {
|
|
||||||
const updatedSort = value
|
|
||||||
.map((sort) => {
|
|
||||||
const option = sortOptions.data.find((o) => o.value === sort.fieldname)
|
|
||||||
return `${option.value} ${sort.direction}`
|
|
||||||
})
|
|
||||||
.join(', ')
|
|
||||||
setOrderBy(updatedSort)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
deep: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => getOrderBy(),
|
|
||||||
(value) => {
|
|
||||||
if (!value) {
|
|
||||||
sortValues.value = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
function setSort(data) {
|
function setSort(data) {
|
||||||
sortValues.value = [
|
sortValues.value.add({ fieldname: data.value, direction: 'asc' })
|
||||||
...sortValues.value,
|
restartSort()
|
||||||
{ fieldname: data.value, direction: 'asc' },
|
apply()
|
||||||
]
|
|
||||||
sortSortable.start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSort(data, index) {
|
function updateSort(data, index) {
|
||||||
sortValues.value[index] = {
|
let oldSort = Array.from(sortValues.value)[index]
|
||||||
|
sortValues.value.delete(oldSort)
|
||||||
|
sortValues.value.add({
|
||||||
fieldname: data.value,
|
fieldname: data.value,
|
||||||
direction: sortValues.value[index].direction,
|
direction: oldSort.direction,
|
||||||
}
|
})
|
||||||
|
apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeSort(index) {
|
function removeSort(index) {
|
||||||
sortValues.value.splice(index, 1)
|
sortValues.value.delete(Array.from(sortValues.value)[index])
|
||||||
|
apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearSort(close) {
|
function clearSort(close) {
|
||||||
sortValues.value = []
|
sortValues.value.clear()
|
||||||
|
apply()
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function apply() {
|
||||||
|
nextTick(() => {
|
||||||
|
emit('update', convertToString(sortValues.value))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertToString(values) {
|
||||||
|
let _sortValues = ''
|
||||||
|
values.forEach((f) => {
|
||||||
|
_sortValues += `${f.fieldname} ${f.direction}, `
|
||||||
|
})
|
||||||
|
_sortValues = _sortValues.slice(0, -2)
|
||||||
|
return _sortValues
|
||||||
|
}
|
||||||
|
|
||||||
|
function restartSort() {
|
||||||
|
sortSortable.stop()
|
||||||
|
sortSortable.start()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,23 +0,0 @@
|
|||||||
import { useRoute, useRouter } from 'vue-router'
|
|
||||||
|
|
||||||
export function useOrderBy() {
|
|
||||||
const route = useRoute()
|
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
function get() {
|
|
||||||
const q = route.query.sort ?? ''
|
|
||||||
const d = decodeURIComponent(q)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
function set(sort, r) {
|
|
||||||
r = r || route
|
|
||||||
const q = encodeURIComponent(sort)
|
|
||||||
router.push({ ...r, query: { ...r.query, sort: q } })
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
get,
|
|
||||||
set,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user