Browse Source

feat: show filter input type and operators based on formula output type

pull/7574/head
Pranav C 7 months ago
parent
commit
151c422fa5
  1. 36
      packages/nc-gui/components/smartsheet/toolbar/ColumnFilter.vue
  2. 33
      packages/nc-gui/composables/useViewFilters.ts
  3. 18
      packages/nocodb-sdk/src/lib/UITypes.ts
  4. 1
      packages/nocodb-sdk/src/lib/index.ts

36
packages/nc-gui/components/smartsheet/toolbar/ColumnFilter.vue

@ -76,6 +76,7 @@ const {
isComparisonSubOpAllowed, isComparisonSubOpAllowed,
loadBtLookupTypes, loadBtLookupTypes,
btLookupTypesMap, btLookupTypesMap,
types,
} = useViewFilters( } = useViewFilters(
activeView, activeView,
parentId?.value, parentId?.value,
@ -114,8 +115,9 @@ const isFilterDraft = (filter: Filter, col: ColumnType) => {
} }
if ( if (
comparisonOpList(col.uidt as UITypes, col?.meta?.date_format).find((compOp) => compOp.value === filter.comparison_op) comparisonOpList(types.value[col.id] as UITypes, col?.meta?.date_format).find(
?.ignoreVal (compOp) => compOp.value === filter.comparison_op,
)?.ignoreVal
) { ) {
return false return false
} }
@ -143,7 +145,7 @@ const filterUpdateCondition = (filter: FilterType, i: number) => {
// hence remove the previous value // hence remove the previous value
filter.value = null filter.value = null
filter.comparison_sub_op = null filter.comparison_sub_op = null
} else if (isDateType(col.uidt as UITypes)) { } else if (isDateType(types.value[col.id] as UITypes)) {
// for date / datetime, // for date / datetime,
// the input type could be decimal or datepicker / datetime picker // the input type could be decimal or datepicker / datetime picker
// hence remove the previous value // hence remove the previous value
@ -173,17 +175,6 @@ const filterUpdateCondition = (filter: FilterType, i: number) => {
}) })
} }
const types = computed(() => {
if (!meta.value?.columns?.length) {
return {}
}
return meta.value?.columns?.reduce((obj: any, col: any) => {
obj[col.id] = col.uidt
return obj
}, {})
})
watch( watch(
() => activeView.value?.id, () => activeView.value?.id,
(n, o) => { (n, o) => {
@ -237,11 +228,11 @@ const selectFilterField = (filter: Filter, index: number) => {
// since the existing one may not be supported for the new field // since the existing one may not be supported for the new field
// e.g. `eq` operator is not supported in checkbox field // e.g. `eq` operator is not supported in checkbox field
// hence, get the first option of the supported operators of the new field // hence, get the first option of the supported operators of the new field
filter.comparison_op = comparisonOpList(col.uidt as UITypes, col?.meta?.date_format).find((compOp) => filter.comparison_op = comparisonOpList(types.value[col.id] as UITypes, col?.meta?.date_format).find((compOp) =>
isComparisonOpAllowed(filter, compOp), isComparisonOpAllowed(filter, compOp),
)?.value as FilterType['comparison_op'] )?.value as FilterType['comparison_op']
if (isDateType(col.uidt as UITypes) && !['blank', 'notblank'].includes(filter.comparison_op!)) { if (isDateType(types.value[col.id] as UITypes) && !['blank', 'notblank'].includes(filter.comparison_op!)) {
if (filter.comparison_op === 'isWithin') { if (filter.comparison_op === 'isWithin') {
filter.comparison_sub_op = 'pastNumberOfDays' filter.comparison_sub_op = 'pastNumberOfDays'
} else { } else {
@ -319,8 +310,9 @@ const showFilterInput = (filter: Filter) => {
(op) => op.value === filter.comparison_sub_op, (op) => op.value === filter.comparison_sub_op,
)?.ignoreVal )?.ignoreVal
} else { } else {
return !comparisonOpList(col?.uidt as UITypes, col?.meta?.date_format).find((op) => op.value === filter.comparison_op) return !comparisonOpList(types.value[col?.id] as UITypes, col?.meta?.date_format).find(
?.ignoreVal (op) => op.value === filter.comparison_op,
)?.ignoreVal
} }
} }
@ -462,7 +454,7 @@ function isDateType(uidt: UITypes) {
@change="filterUpdateCondition(filter, i)" @change="filterUpdateCondition(filter, i)"
> >
<template <template
v-for="compOp of comparisonOpList(getColumn(filter)?.uidt, getColumn(filter)?.meta?.date_format)" v-for="compOp of comparisonOpList(types[filter.fk_column_id], getColumn(filter)?.meta?.date_format)"
:key="compOp.value" :key="compOp.value"
> >
<a-select-option v-if="isComparisonOpAllowed(filter, compOp)" :value="compOp.value"> <a-select-option v-if="isComparisonOpAllowed(filter, compOp)" :value="compOp.value">
@ -481,7 +473,7 @@ function isDateType(uidt: UITypes) {
<div v-if="['blank', 'notblank'].includes(filter.comparison_op)" class="flex flex-grow"></div> <div v-if="['blank', 'notblank'].includes(filter.comparison_op)" class="flex flex-grow"></div>
<NcSelect <NcSelect
v-else-if="isDateType(getColumn(filter)?.uidt)" v-else-if="isDateType(types[filter.fk_column_id])"
v-model:value="filter.comparison_sub_op" v-model:value="filter.comparison_sub_op"
v-e="['c:filter:sub-comparison-op:select']" v-e="['c:filter:sub-comparison-op:select']"
:dropdown-match-select-width="false" :dropdown-match-select-width="false"
@ -529,12 +521,12 @@ function isDateType(uidt: UITypes) {
<SmartsheetToolbarFilterInput <SmartsheetToolbarFilterInput
v-if="showFilterInput(filter)" v-if="showFilterInput(filter)"
class="nc-filter-value-select rounded-md min-w-34" class="nc-filter-value-select rounded-md min-w-34"
:column="getColumn(filter)" :column="{ ...getColumn(filter), uidt: types[filter.fk_column_id] }"
:filter="filter" :filter="filter"
@update-filter-value="(value) => updateFilterValue(value, filter, i)" @update-filter-value="(value) => updateFilterValue(value, filter, i)"
@click.stop @click.stop
/> />
<div v-else-if="!isDateType(getColumn(filter)?.uidt)" class="flex-grow"></div> <div v-else-if="!isDateType(types[filter.fk_column_id])" class="flex-grow"></div>
<NcButton <NcButton
v-if="!filter.readOnly" v-if="!filter.readOnly"

33
packages/nc-gui/composables/useViewFilters.ts

@ -1,4 +1,13 @@
import type { ColumnType, FilterType, LinkToAnotherRecordType, LookupType, ViewType } from 'nocodb-sdk' import {
type ColumnType,
type FilterType,
FormulaDataTypes,
type FormulaType,
type LinkToAnotherRecordType,
type LookupType,
type ViewType,
getEquivalentUIType,
} from 'nocodb-sdk'
import type { ComputedRef, Ref } from 'vue' import type { ComputedRef, Ref } from 'vue'
import type { SelectProps } from 'ant-design-vue' import type { SelectProps } from 'ant-design-vue'
import { UITypes, isSystemColumn } from 'nocodb-sdk' import { UITypes, isSystemColumn } from 'nocodb-sdk'
@ -103,8 +112,15 @@ export function useViewFilters(
} }
return meta.value?.columns?.reduce((obj: any, col: any) => { return meta.value?.columns?.reduce((obj: any, col: any) => {
if (col.uidt === UITypes.Formula) {
const formulaUIType = getEquivalentUIType({
formulaColumn: col,
})
obj[col.id] = formulaUIType || col.uidt
}
// if column is a lookup column, then use the lookup type extracted from the column // if column is a lookup column, then use the lookup type extracted from the column
if (btLookupTypesMap.value[col.id]) { else if (btLookupTypesMap.value[col.id]) {
obj[col.id] = btLookupTypesMap.value[col.id].uidt obj[col.id] = btLookupTypesMap.value[col.id].uidt
} else { } else {
obj[col.id] = col.uidt obj[col.id] = col.uidt
@ -137,9 +153,11 @@ export function useViewFilters(
}, },
) => { ) => {
const isNullOrEmptyOp = ['empty', 'notempty', 'null', 'notnull'].includes(compOp.value) const isNullOrEmptyOp = ['empty', 'notempty', 'null', 'notnull'].includes(compOp.value)
const uidt = types.value[filter.fk_column_id]
if (compOp.includedTypes) { if (compOp.includedTypes) {
// include allowed values only if selected column type matches // include allowed values only if selected column type matches
if (filter.fk_column_id && compOp.includedTypes.includes(types.value[filter.fk_column_id])) { if (filter.fk_column_id && compOp.includedTypes.includes(uidt)) {
// for 'empty', 'notempty', 'null', 'notnull', // for 'empty', 'notempty', 'null', 'notnull',
// show them based on `showNullAndEmptyInFilter` in Base Settings // show them based on `showNullAndEmptyInFilter` in Base Settings
return isNullOrEmptyOp ? baseMeta.value.showNullAndEmptyInFilter : true return isNullOrEmptyOp ? baseMeta.value.showNullAndEmptyInFilter : true
@ -148,7 +166,7 @@ export function useViewFilters(
} }
} else if (compOp.excludedTypes) { } else if (compOp.excludedTypes) {
// include not allowed values only if selected column type not matches // include not allowed values only if selected column type not matches
if (filter.fk_column_id && !compOp.excludedTypes.includes(types.value[filter.fk_column_id])) { if (filter.fk_column_id && !compOp.excludedTypes.includes(uidt)) {
// for 'empty', 'notempty', 'null', 'notnull', // for 'empty', 'notempty', 'null', 'notnull',
// show them based on `showNullAndEmptyInFilter` in Base Settings // show them based on `showNullAndEmptyInFilter` in Base Settings
return isNullOrEmptyOp ? baseMeta.value.showNullAndEmptyInFilter : true return isNullOrEmptyOp ? baseMeta.value.showNullAndEmptyInFilter : true
@ -170,12 +188,14 @@ export function useViewFilters(
excludedTypes?: UITypes[] excludedTypes?: UITypes[]
}, },
) => { ) => {
const uidt = types.value[filter.fk_column_id]
if (compOp.includedTypes) { if (compOp.includedTypes) {
// include allowed values only if selected column type matches // include allowed values only if selected column type matches
return filter.fk_column_id && compOp.includedTypes.includes(types.value[filter.fk_column_id]) return filter.fk_column_id && compOp.includedTypes.includes(uidt)
} else if (compOp.excludedTypes) { } else if (compOp.excludedTypes) {
// include not allowed values only if selected column type not matches // include not allowed values only if selected column type not matches
return filter.fk_column_id && !compOp.excludedTypes.includes(types.value[filter.fk_column_id]) return filter.fk_column_id && !compOp.excludedTypes.includes(uidt)
} }
} }
@ -479,5 +499,6 @@ export function useViewFilters(
isComparisonSubOpAllowed, isComparisonSubOpAllowed,
loadBtLookupTypes, loadBtLookupTypes,
btLookupTypesMap, btLookupTypesMap,
types
} }
} }

18
packages/nocodb-sdk/src/lib/UITypes.ts

@ -1,4 +1,5 @@
import { ColumnReqType, ColumnType } from './Api'; import { ColumnReqType, ColumnType } from './Api';
import { FormulaDataTypes } from './formulaHelpers';
enum UITypes { enum UITypes {
ID = 'ID', ID = 'ID',
@ -185,4 +186,21 @@ export function isLinksOrLTAR(
); );
} }
export const getEquivalentUIType = ({
formulaColumn,
}: {
formulaColumn: ColumnType;
}): void | UITypes => {
switch ((formulaColumn?.colOptions as any)?.parsed_tree?.dataType) {
case FormulaDataTypes.NUMERIC:
return UITypes.Number;
case FormulaDataTypes.DATE:
return UITypes.DateTime;
// case FormulaDataTypes.LOGICAL:
// case FormulaDataTypes.BOOLEAN:
// uidt = UITypes.Number;
// break
}
};
export default UITypes; export default UITypes;

1
packages/nocodb-sdk/src/lib/index.ts

@ -17,6 +17,7 @@ export {
isCreatedOrLastModifiedTimeCol, isCreatedOrLastModifiedTimeCol,
isCreatedOrLastModifiedByCol, isCreatedOrLastModifiedByCol,
isHiddenCol, isHiddenCol,
getEquivalentUIType,
} from '~/lib/UITypes'; } from '~/lib/UITypes';
export { default as CustomAPI, FileType } from '~/lib/CustomAPI'; export { default as CustomAPI, FileType } from '~/lib/CustomAPI';
export { default as TemplateGenerator } from '~/lib/TemplateGenerator'; export { default as TemplateGenerator } from '~/lib/TemplateGenerator';

Loading…
Cancel
Save