Browse Source

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

pull/7574/head
Pranav C 5 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,
loadBtLookupTypes,
btLookupTypesMap,
types,
} = useViewFilters(
activeView,
parentId?.value,
@ -114,8 +115,9 @@ const isFilterDraft = (filter: Filter, col: ColumnType) => {
}
if (
comparisonOpList(col.uidt as UITypes, col?.meta?.date_format).find((compOp) => compOp.value === filter.comparison_op)
?.ignoreVal
comparisonOpList(types.value[col.id] as UITypes, col?.meta?.date_format).find(
(compOp) => compOp.value === filter.comparison_op,
)?.ignoreVal
) {
return false
}
@ -143,7 +145,7 @@ const filterUpdateCondition = (filter: FilterType, i: number) => {
// hence remove the previous value
filter.value = 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,
// the input type could be decimal or datepicker / datetime picker
// 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(
() => activeView.value?.id,
(n, o) => {
@ -237,11 +228,11 @@ const selectFilterField = (filter: Filter, index: number) => {
// since the existing one may not be supported for the new field
// e.g. `eq` operator is not supported in checkbox 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),
)?.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') {
filter.comparison_sub_op = 'pastNumberOfDays'
} else {
@ -319,8 +310,9 @@ const showFilterInput = (filter: Filter) => {
(op) => op.value === filter.comparison_sub_op,
)?.ignoreVal
} else {
return !comparisonOpList(col?.uidt as UITypes, col?.meta?.date_format).find((op) => op.value === filter.comparison_op)
?.ignoreVal
return !comparisonOpList(types.value[col?.id] as UITypes, col?.meta?.date_format).find(
(op) => op.value === filter.comparison_op,
)?.ignoreVal
}
}
@ -462,7 +454,7 @@ function isDateType(uidt: UITypes) {
@change="filterUpdateCondition(filter, i)"
>
<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"
>
<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>
<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-e="['c:filter:sub-comparison-op:select']"
:dropdown-match-select-width="false"
@ -529,12 +521,12 @@ function isDateType(uidt: UITypes) {
<SmartsheetToolbarFilterInput
v-if="showFilterInput(filter)"
class="nc-filter-value-select rounded-md min-w-34"
:column="getColumn(filter)"
:column="{ ...getColumn(filter), uidt: types[filter.fk_column_id] }"
:filter="filter"
@update-filter-value="(value) => updateFilterValue(value, filter, i)"
@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
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 { SelectProps } from 'ant-design-vue'
import { UITypes, isSystemColumn } from 'nocodb-sdk'
@ -103,8 +112,15 @@ export function useViewFilters(
}
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 (btLookupTypesMap.value[col.id]) {
else if (btLookupTypesMap.value[col.id]) {
obj[col.id] = btLookupTypesMap.value[col.id].uidt
} else {
obj[col.id] = col.uidt
@ -137,9 +153,11 @@ export function useViewFilters(
},
) => {
const isNullOrEmptyOp = ['empty', 'notempty', 'null', 'notnull'].includes(compOp.value)
const uidt = types.value[filter.fk_column_id]
if (compOp.includedTypes) {
// 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',
// show them based on `showNullAndEmptyInFilter` in Base Settings
return isNullOrEmptyOp ? baseMeta.value.showNullAndEmptyInFilter : true
@ -148,7 +166,7 @@ export function useViewFilters(
}
} else if (compOp.excludedTypes) {
// 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',
// show them based on `showNullAndEmptyInFilter` in Base Settings
return isNullOrEmptyOp ? baseMeta.value.showNullAndEmptyInFilter : true
@ -170,12 +188,14 @@ export function useViewFilters(
excludedTypes?: UITypes[]
},
) => {
const uidt = types.value[filter.fk_column_id]
if (compOp.includedTypes) {
// 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) {
// 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,
loadBtLookupTypes,
btLookupTypesMap,
types
}
}

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

@ -1,4 +1,5 @@
import { ColumnReqType, ColumnType } from './Api';
import { FormulaDataTypes } from './formulaHelpers';
enum UITypes {
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;

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

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

Loading…
Cancel
Save