Merge pull request #184 from frappe/develop
chore: Merge develop to main
This commit is contained in:
commit
3f5c7a14aa
@ -126,6 +126,30 @@ def get_fields_meta(DocField, doctype, allowed_fieldtypes, restricted_fields):
|
|||||||
.run(as_dict=True)
|
.run(as_dict=True)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_quick_filters(doctype: str):
|
||||||
|
meta = frappe.get_meta(doctype)
|
||||||
|
fields = [field for field in meta.fields if field.in_standard_filter]
|
||||||
|
quick_filters = []
|
||||||
|
|
||||||
|
for field in fields:
|
||||||
|
|
||||||
|
if field.fieldtype == "Select":
|
||||||
|
field.options = field.options.split("\n")
|
||||||
|
field.options = [{"label": option, "value": option} for option in field.options]
|
||||||
|
field.options.insert(0, {"label": "", "value": ""})
|
||||||
|
quick_filters.append({
|
||||||
|
"label": _(field.label),
|
||||||
|
"name": field.fieldname,
|
||||||
|
"type": field.fieldtype,
|
||||||
|
"options": field.options,
|
||||||
|
})
|
||||||
|
|
||||||
|
if doctype == "CRM Lead":
|
||||||
|
quick_filters = [filter for filter in quick_filters if filter.get("name") != "converted"]
|
||||||
|
|
||||||
|
return quick_filters
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_list_data(
|
def get_list_data(
|
||||||
doctype: str,
|
doctype: str,
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
'form-input block h-7 w-full cursor-pointer select-none rounded border-gray-400 text-sm placeholder-gray-500',
|
'form-input block h-7 w-full cursor-pointer select-none rounded border-gray-400 text-sm placeholder-gray-500',
|
||||||
inputClass,
|
inputClass,
|
||||||
]"
|
]"
|
||||||
|
v-bind="$attrs"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ togglePopover }">
|
<template #body="{ togglePopover }">
|
||||||
|
|||||||
@ -178,7 +178,7 @@ function convertFilters(data, allFilters) {
|
|||||||
let field = data.find((f) => f.fieldname === key)
|
let field = data.find((f) => f.fieldname === key)
|
||||||
if (typeof value !== 'object') {
|
if (typeof value !== 'object') {
|
||||||
value = ['=', value]
|
value = ['=', value]
|
||||||
if (field.fieldtype === 'Check') {
|
if (field?.fieldtype === 'Check') {
|
||||||
value = ['equals', value[1] ? 'Yes' : 'No']
|
value = ['equals', value[1] ? 'Yes' : 'No']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,6 +276,8 @@ function getOperators(fieldtype, fieldname) {
|
|||||||
if (typeDate.includes(fieldtype)) {
|
if (typeDate.includes(fieldtype)) {
|
||||||
options.push(
|
options.push(
|
||||||
...[
|
...[
|
||||||
|
{ label: __('Equals'), value: 'equals' },
|
||||||
|
{ label: __('Not Equals'), value: 'not equals' },
|
||||||
{ label: __('Is'), value: 'is' },
|
{ label: __('Is'), value: 'is' },
|
||||||
{ label: __('>'), value: '>' },
|
{ label: __('>'), value: '>' },
|
||||||
{ label: __('<'), value: '<' },
|
{ label: __('<'), value: '<' },
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center justify-between px-5 py-4">
|
<div class="flex items-center justify-between gap-2 px-5 py-4">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<Dropdown :options="viewsDropdownOptions">
|
<Dropdown :options="viewsDropdownOptions">
|
||||||
<template #default="{ open }">
|
<template #default="{ open }">
|
||||||
@ -22,6 +22,64 @@
|
|||||||
</template>
|
</template>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="-mr-2 h-[70%] border-l" />
|
||||||
|
<div
|
||||||
|
class="flex flex-1 items-center overflow-x-auto px-1"
|
||||||
|
style="
|
||||||
|
mask-image: linear-gradient(
|
||||||
|
to right,
|
||||||
|
black calc(100% - 20px),
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="filter in quickFilterList"
|
||||||
|
:key="filter.name"
|
||||||
|
class="m-1 min-w-36"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
v-if="filter.type == 'Check'"
|
||||||
|
:label="filter.label"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="filter.value"
|
||||||
|
@change.stop="applyQuickFilter(filter, $event.target.checked)"
|
||||||
|
/>
|
||||||
|
<FormControl
|
||||||
|
v-else-if="filter.type === 'Select'"
|
||||||
|
class="form-control cursor-pointer [&_select]:cursor-pointer"
|
||||||
|
type="select"
|
||||||
|
v-model="filter.value"
|
||||||
|
:options="filter.options"
|
||||||
|
:placeholder="filter.label"
|
||||||
|
@change.stop="applyQuickFilter(filter, $event.target.value)"
|
||||||
|
/>
|
||||||
|
<Link
|
||||||
|
v-else-if="filter.type === 'Link'"
|
||||||
|
:value="filter.value"
|
||||||
|
:doctype="filter.options"
|
||||||
|
:placeholder="filter.label"
|
||||||
|
@change="(data) => applyQuickFilter(filter, data)"
|
||||||
|
/>
|
||||||
|
<component
|
||||||
|
v-else-if="['Date', 'Datetime'].includes(filter.type)"
|
||||||
|
class="border-none"
|
||||||
|
:is="filter.type === 'Date' ? DatePicker : DatetimePicker"
|
||||||
|
:value="filter.value"
|
||||||
|
@change="(v) => applyQuickFilter(filter, v)"
|
||||||
|
:placeholder="filter.label"
|
||||||
|
/>
|
||||||
|
<FormControl
|
||||||
|
v-else
|
||||||
|
:value="filter.value"
|
||||||
|
type="text"
|
||||||
|
:placeholder="filter.label"
|
||||||
|
:debounce="500"
|
||||||
|
@change.stop="applyQuickFilter(filter, $event.target.value)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="-ml-2 h-[70%] border-l" />
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<div
|
<div
|
||||||
v-if="viewUpdated && route.query.view && (!view.public || isManager())"
|
v-if="viewUpdated && route.query.view && (!view.public || isManager())"
|
||||||
@ -131,6 +189,9 @@
|
|||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import DatePicker from '@/components/Controls/DatePicker.vue'
|
||||||
|
import DatetimePicker from '@/components/Controls/DatetimePicker.vue'
|
||||||
|
import Link from '@/components/Controls/Link.vue'
|
||||||
import RefreshIcon from '@/components/Icons/RefreshIcon.vue'
|
import RefreshIcon from '@/components/Icons/RefreshIcon.vue'
|
||||||
import EditIcon from '@/components/Icons/EditIcon.vue'
|
import EditIcon from '@/components/Icons/EditIcon.vue'
|
||||||
import DuplicateIcon from '@/components/Icons/DuplicateIcon.vue'
|
import DuplicateIcon from '@/components/Icons/DuplicateIcon.vue'
|
||||||
@ -384,6 +445,51 @@ const viewsDropdownOptions = computed(() => {
|
|||||||
return _views
|
return _views
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const quickFilterList = computed(() => {
|
||||||
|
let filters = [{ name: 'name', label: __('ID') }]
|
||||||
|
if (quickFilters.data) {
|
||||||
|
filters.push(...quickFilters.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
filters.forEach((filter) => {
|
||||||
|
filter['value'] = filter.type == 'Check' ? false : ''
|
||||||
|
if (list.value.params?.filters[filter.name]) {
|
||||||
|
let value = list.value.params.filters[filter.name]
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
filter['value'] = value[1].replace(/%/g, '')
|
||||||
|
} else {
|
||||||
|
filter['value'] = value.replace(/%/g, '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return filters
|
||||||
|
})
|
||||||
|
|
||||||
|
const quickFilters = createResource({
|
||||||
|
url: 'crm.api.doc.get_quick_filters',
|
||||||
|
params: { doctype: props.doctype },
|
||||||
|
cache: ['Quick Filters', props.doctype],
|
||||||
|
auto: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
function applyQuickFilter(filter, value) {
|
||||||
|
let filters = { ...list.value.params.filters }
|
||||||
|
let field = filter.name
|
||||||
|
if (value) {
|
||||||
|
if (['Check', 'Select', 'Link', 'Date', 'Datetime'].includes(filter.type)) {
|
||||||
|
filters[field] = value
|
||||||
|
} else {
|
||||||
|
filters[field] = ['LIKE', `%${value}%`]
|
||||||
|
}
|
||||||
|
filter['value'] = value
|
||||||
|
} else {
|
||||||
|
delete filters[field]
|
||||||
|
filter['value'] = ''
|
||||||
|
}
|
||||||
|
updateFilter(filters)
|
||||||
|
}
|
||||||
|
|
||||||
function updateFilter(filters) {
|
function updateFilter(filters) {
|
||||||
viewUpdated.value = true
|
viewUpdated.value = true
|
||||||
if (!defaultParams.value) {
|
if (!defaultParams.value) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user