feat: customize quick filter option and UI
This commit is contained in:
parent
d83a326a6a
commit
facf98d1d0
16
frontend/src/components/Icons/ExportIcon.vue
Normal file
16
frontend/src/components/Icons/ExportIcon.vue
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<template>
|
||||||
|
<svg
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M8 10V2M8 2L5.33333 4.66663M8 2L10.6667 4.66663M11.8571 6.99996H13C13.5523 6.99996 14 7.44767 14 7.99996V13C14 13.5522 13.5523 14 13 14H3C2.44772 14 2 13.5522 2 13V7.99996C2 7.44767 2.44772 6.99996 3 6.99996H4.14286"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
20
frontend/src/components/Icons/QuickFilterIcon.vue
Normal file
20
frontend/src/components/Icons/QuickFilterIcon.vue
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<template>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-list-filter-plus"
|
||||||
|
>
|
||||||
|
<path d="M10 18h4" />
|
||||||
|
<path d="M11 6H3" />
|
||||||
|
<path d="M15 6h6" />
|
||||||
|
<path d="M18 9V3" />
|
||||||
|
<path d="M7 12h8" />
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
@ -58,6 +58,62 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="customizeQuickFilter"
|
||||||
|
class="flex items-center justify-between gap-2 p-5"
|
||||||
|
>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<template v-for="filter in newQuickFilters" :key="filter.fieldname">
|
||||||
|
<Tooltip :text="filter.fieldname">
|
||||||
|
<Button :label="filter.label" class="group">
|
||||||
|
<template #suffix>
|
||||||
|
<FeatherIcon
|
||||||
|
class="h-3.5 cursor-pointer group-hover:flex hidden"
|
||||||
|
name="x"
|
||||||
|
@click.stop="removeQuickFilter(filter)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</template>
|
||||||
|
<Autocomplete
|
||||||
|
value=""
|
||||||
|
:options="quickFilterOptions"
|
||||||
|
@change="(e) => addQuickFilter(e)"
|
||||||
|
>
|
||||||
|
<template #target="{ togglePopover }">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
@click="togglePopover()"
|
||||||
|
:label="__('Add filter')"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<FeatherIcon name="plus" class="h-4" />
|
||||||
|
</template>
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
<template #item-label="{ option }">
|
||||||
|
<Tooltip :text="option.value" :hover-delay="1">
|
||||||
|
<div class="flex-1 truncate text-ink-gray-7">
|
||||||
|
{{ option.label }}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</template>
|
||||||
|
</Autocomplete>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-1">
|
||||||
|
<Button
|
||||||
|
:label="__('Save')"
|
||||||
|
:loading="updateQuickFilters.loading"
|
||||||
|
@click="saveQuickFilters"
|
||||||
|
/>
|
||||||
|
<Button @click="customizeQuickFilter = false">
|
||||||
|
<template #icon>
|
||||||
|
<FeatherIcon name="x" class="h-4 w-4" />
|
||||||
|
</template>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div v-else class="flex items-center justify-between gap-2 px-5 py-4">
|
<div v-else class="flex items-center justify-between gap-2 px-5 py-4">
|
||||||
<FadedScrollableDiv
|
<FadedScrollableDiv
|
||||||
class="flex flex-1 items-center overflow-x-auto -ml-1"
|
class="flex flex-1 items-center overflow-x-auto -ml-1"
|
||||||
@ -130,10 +186,14 @@
|
|||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
label: __('Export'),
|
label: __('Export'),
|
||||||
icon: () =>
|
icon: () => h(ExportIcon, { class: 'h-4 w-4' }),
|
||||||
h(FeatherIcon, { name: 'download', class: 'h-4 w-4' }),
|
|
||||||
onClick: () => (showExportDialog = true),
|
onClick: () => (showExportDialog = true),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: __('Customize quick filters'),
|
||||||
|
icon: () => h(QuickFilterIcon, { class: 'h-4 w-4' }),
|
||||||
|
onClick: () => (customizeQuickFilter = true),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
@ -218,7 +278,10 @@ import DuplicateIcon from '@/components/Icons/DuplicateIcon.vue'
|
|||||||
import CheckIcon from '@/components/Icons/CheckIcon.vue'
|
import CheckIcon from '@/components/Icons/CheckIcon.vue'
|
||||||
import PinIcon from '@/components/Icons/PinIcon.vue'
|
import PinIcon from '@/components/Icons/PinIcon.vue'
|
||||||
import UnpinIcon from '@/components/Icons/UnpinIcon.vue'
|
import UnpinIcon from '@/components/Icons/UnpinIcon.vue'
|
||||||
|
import ExportIcon from '@/components/Icons/ExportIcon.vue'
|
||||||
|
import QuickFilterIcon from '@/components/Icons/QuickFilterIcon.vue'
|
||||||
import ViewModal from '@/components/Modals/ViewModal.vue'
|
import ViewModal from '@/components/Modals/ViewModal.vue'
|
||||||
|
import Autocomplete from '@/components/frappe-ui/Autocomplete.vue'
|
||||||
import SortBy from '@/components/SortBy.vue'
|
import SortBy from '@/components/SortBy.vue'
|
||||||
import Filter from '@/components/Filter.vue'
|
import Filter from '@/components/Filter.vue'
|
||||||
import GroupBy from '@/components/GroupBy.vue'
|
import GroupBy from '@/components/GroupBy.vue'
|
||||||
@ -229,8 +292,10 @@ import { getSettings } from '@/stores/settings'
|
|||||||
import { globalStore } from '@/stores/global'
|
import { globalStore } from '@/stores/global'
|
||||||
import { viewsStore } from '@/stores/views'
|
import { viewsStore } from '@/stores/views'
|
||||||
import { usersStore } from '@/stores/users'
|
import { usersStore } from '@/stores/users'
|
||||||
import { isEmoji } from '@/utils'
|
import { getMeta } from '@/stores/meta'
|
||||||
|
import { isEmoji, createToast } from '@/utils'
|
||||||
import {
|
import {
|
||||||
|
Tooltip,
|
||||||
createResource,
|
createResource,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
call,
|
call,
|
||||||
@ -594,11 +659,28 @@ const viewsDropdownOptions = computed(() => {
|
|||||||
return _views
|
return _views
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { getFields } = getMeta(props.doctype)
|
||||||
|
|
||||||
|
const customizeQuickFilter = ref(false)
|
||||||
|
|
||||||
|
const newQuickFilters = ref([])
|
||||||
|
|
||||||
|
function addQuickFilter(f) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeQuickFilter(f) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveQuickFilters() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
const quickFilterOptions = []
|
||||||
|
|
||||||
const quickFilterList = computed(() => {
|
const quickFilterList = computed(() => {
|
||||||
let filters = [{ fieldname: 'name', fieldtype: 'Data', label: __('ID') }]
|
let filters = quickFilters.data || []
|
||||||
if (quickFilters.data) {
|
|
||||||
filters.push(...quickFilters.data)
|
|
||||||
}
|
|
||||||
|
|
||||||
filters.forEach((filter) => {
|
filters.forEach((filter) => {
|
||||||
filter['value'] = filter.fieldtype == 'Check' ? false : ''
|
filter['value'] = filter.fieldtype == 'Check' ? false : ''
|
||||||
@ -630,6 +712,13 @@ const quickFilters = createResource({
|
|||||||
params: { doctype: props.doctype },
|
params: { doctype: props.doctype },
|
||||||
cache: ['Quick Filters', props.doctype],
|
cache: ['Quick Filters', props.doctype],
|
||||||
auto: true,
|
auto: true,
|
||||||
|
onSuccess(filters) {
|
||||||
|
newQuickFilters.value = filters.map((f) => ({
|
||||||
|
label: f.label,
|
||||||
|
fieldname: f.fieldname,
|
||||||
|
fieldtype: f.fieldtype,
|
||||||
|
}))
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
function applyQuickFilter(filter, value) {
|
function applyQuickFilter(filter, value) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user