3
0

Add between and not between operators functionality

This commit is contained in:
Kelani Tolulope 2023-01-10 15:11:48 +01:00 committed by Vivek Patel
parent ba15a3ba96
commit f761d0183b
3 changed files with 135 additions and 29 deletions

View File

@ -86,20 +86,48 @@
v-model="filter.operator"
:options="getOperators(filter.kind, getField(filter.name))"
class="d-flex field-operator w-100"
@change="updateFilterProperties(filter)"
/>
</b-td>
<b-td
v-if="getField(filter.name)"
>
<field-editor
v-bind="mock"
class="field-editor mb-0"
value-only
:field="getField(filter.name)"
:record="filter.record"
:operator="filter.operator"
@change="onValueChange"
/>
<template v-if="isBetweenOperator(filter.operator)">
<template
v-if="getField(`${filter.name}-start`)"
>
<field-editor
v-bind="mock"
class="field-editor mb-0"
value-only
:field="getField(`${filter.name}-start`)"
:record="filter.record"
@change="onValueChange"
/>
<span class="text-center my-1 w-100">
{{ $t('general.label.and') }}
</span>
<field-editor
v-bind="mock"
class="field-editor mb-0"
value-only
:field="getField(`${filter.name}-end`)"
:record="filter.record"
@change="onValueChange"
/>
</template>
</template>
<template v-else>
<field-editor
v-bind="mock"
class="field-editor mb-0"
value-only
:field="getField(filter.name)"
:record="filter.record"
@change="onValueChange"
/>
</template>
</b-td>
<b-td
v-if="getField(filter.name)"
@ -390,16 +418,27 @@ export default {
},
]
const betweenOperators = [
{
value: 'BETWEEN',
text: this.$t('recordList.filter.operators.between'),
},
{
value: 'NOT BETWEEN',
text: this.$t('recordList.filter.operators.notBetween'),
},
]
if (field.multi) {
return inOperators
}
switch (kind) {
case 'Number':
return [...operators, ...lgOperators]
return [...operators, ...lgOperators, ...betweenOperators]
case 'DateTime':
return [...operators, ...lgOperators]
return [...operators, ...lgOperators, ...betweenOperators]
case 'String':
case 'Url':
@ -499,8 +538,21 @@ export default {
filter = filter.map(({ value, ...f }) => {
f.record = new compose.Record(this.mock.module, {})
// If its a system field add value to root of record
if (Object.keys(f.record).includes(f.name)) {
if (this.isBetweenOperator(f.operator)) {
if (this.getField(f.name).isSystem) {
f.record[`${f.name}-start`] = value.start
f.record[`${f.name}-end`] = value.end
} else {
f.record.values[`${f.name}-start`] = value.start
f.record.values[`${f.name}-end`] = value.end
}
const field = this.mock.module.fields.find(field => field.name === f.name)
this.mock.module.fields.push({ ...field, name: `${f.name}-end` })
this.mock.module.fields.push({ ...field, name: `${f.name}-start` })
} else if (Object.keys(f.record).includes(f.name)) {
// If its a system field add value to root of record
f.record[f.name] = value
} else {
f.record.values[f.name] = value
@ -531,12 +583,35 @@ export default {
f.value = record[f.name] || record.values[f.name]
}
if (this.isBetweenOperator(f.operator)) {
f.value = {
start: this.getField(f.name).isSystem ? record[`${f.name}-start`] : record.values[`${f.name}-start`],
end: this.getField(f.name).isSystem ? record[`${f.name}-end`] : record.values[`${f.name}-end`],
}
}
return f
})
return { groupCondition, filter }
}))
},
updateFilterProperties (filter) {
if (this.isBetweenOperator(filter.operator)) {
filter.record.values[`${filter.name}-start`] = filter.record.values[`${filter.name}-start`]
filter.record.values[`${filter.name}-end`] = filter.record.values[`${filter.name}-end`]
const field = this.mock.module.fields.find(f => f.name === filter.name)
this.mock.module.fields.push({ ...field, name: `${filter.name}-end` })
this.mock.module.fields.push({ ...field, name: `${filter.name}-start` })
}
},
isBetweenOperator (op) {
return ['BETWEEN', 'NOT BETWEEN'].includes(op)
},
},
}
</script>

View File

@ -16,6 +16,7 @@ export function getRecordListFilterSql (filter) {
}
const fieldFilter = getFieldFilter(f.name, f.kind, f.value, f.operator)
if (fieldFilter) {
query += getFieldFilter(f.name, f.kind, f.value, f.operator)
existsPreviousElement = true
@ -28,9 +29,13 @@ export function getRecordListFilterSql (filter) {
// Helper function that creates a query for a specific field kind
export function getFieldFilter (name, kind, query = '', operator = '=') {
const boolQuery = toBoolean(query)
const numQuery = Number.parseFloat(query)
let boolQuery = query
let numQuery = query
if (typeof query === 'object' && query !== null) {
boolQuery = toBoolean(query)
numQuery = Number.parseFloat(query)
}
const build = (op, left, right) => {
switch (op.toUpperCase()) {
case '!=':
@ -39,7 +44,10 @@ export function getFieldFilter (name, kind, query = '', operator = '=') {
case 'IN':
case 'NOT IN':
// flip left/right for IN/NOT IN
return `${right} ${op} ${left}`
return `'${right}' ${op} ${left}`
case 'BETWEEN':
case 'NOT BETWEEN':
return `${name} ${op} ${query.start} ${query.end}`
default:
return `${left} ${op} ${right}`
}
@ -68,23 +76,43 @@ export function getFieldFilter (name, kind, query = '', operator = '=') {
return undefined
}
if (['Number'].includes(kind) && !isNaN(numQuery)) {
return build(operator, name, `'${numQuery}'`)
if (['Number'].includes(kind)) {
if (['BETWEEN', 'NOT BETWEEN'].includes(operator)) {
return build(operator, name, numQuery)
} else if (!isNaN(numQuery)) {
return build(operator, name, numQuery)
}
}
if (['DateTime'].includes(kind)) {
// Build different querries if date, time or datetime
const date = moment(query, ['YYYY-MM-DDTHH:mm:ssZ', 'YYYY-MM-DD'])
const time = moment(query, ['HH:mm'])
if (['BETWEEN', 'NOT BETWEEN'].includes(operator)) {
const startDate = moment(query.start, ['YYYY-MM-DDTHH:mm:ssZ', 'YYYY-MM-DD'])
const endDate = moment(query.end, ['YYYY-MM-DDTHH:mm:ssZ', 'YYYY-MM-DD'])
// @note tweaking the template a bit:
// * adding %f to include fractions; mysql sometimes forces them when formatting date
// * changing Z to +00:00
// * doing the same for time-only fields
if (date.isValid()) {
return `TIMESTAMP(DATE_FORMAT(${name}, '%Y-%m-%dT%H:%i:00.%f+00:00')) ${operator} TIMESTAMP(DATE_FORMAT('${date.format()}', '%Y-%m-%dT%H:%i:00.%f+00:00'))`
} else if (time.isValid()) {
return `TIME(DATE_FORMAT(${name}, '%Y-%m-%dT%H:%i:00.%f+00:00')) ${operator} TIME('${query}')`
const startTime = moment(query.start, ['HH:mm'])
const endTime = moment(query.end, ['HH:mm'])
const dataFmtEntry = (date) => `TIMESTAMP(DATE_FORMAT('${date.format()}', '%Y-%m-%dT%H:%i:00.%f+00:00'))`
if (startDate.isValid() && endDate.isValid()) {
return `TIMESTAMP(DATE_FORMAT(${name}, '%Y-%m-%dT%H:%i:00.%f+00:00')) ${operator} ${dataFmtEntry(startDate)} ${dataFmtEntry(endDate)}`
} else if (startTime.isValid() && endTime.isValid()) {
return `TIME(DATE_FORMAT(${name}, '%Y-%m-%dT%H:%i:00.%f+00:00')) ${operator} TIME('${query.start}') TIME('${query.end}')`
}
} else {
// Build different querries if date, time or datetime
const date = moment(query, ['YYYY-MM-DDTHH:mm:ssZ', 'YYYY-MM-DD'])
const time = moment(query, ['HH:mm'])
// @note tweaking the template a bit:
// * adding %f to include fractions; mysql sometimes forces them when formatting date
// * changing Z to +00:00
// * doing the same for time-only fields
if (date.isValid()) {
return `TIMESTAMP(DATE_FORMAT(${name}, '%Y-%m-%dT%H:%i:00.%f+00:00')) ${operator} TIMESTAMP(DATE_FORMAT('${date.format()}', '%Y-%m-%dT%H:%i:00.%f+00:00'))`
} else if (time.isValid()) {
return `TIME(DATE_FORMAT(${name}, '%Y-%m-%dT%H:%i:00.%f+00:00')) ${operator} TIME('${query}')`
}
}
}

View File

@ -138,6 +138,7 @@ general:
save: Save
search: Search
magnify: Magnify Block
and: And
module: Module
style:
danger: Danger variant
@ -281,6 +282,8 @@ recordList:
greaterThan: Greater than
lessThan: Less than
notEqual: Not equal
between: Between
notBetween: Not between
title: Record list filter
update: Update filter
where: Where