多维表格
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
4.7 KiB

<script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk'
import {
ColumnInj,
EditModeInj,
ReadonlyInj,
computed,
isBoolean,
isCurrency,
isDate,
isDateTime,
isDecimal,
isDuration,
isFloat,
isInt,
isMultiSelect,
isPercent,
isRating,
isSingleSelect,
isTextArea,
isTime,
isYear,
provide,
ref,
toRef,
useProject,
} from '#imports'
import type { Filter } from '~/lib'
import SingleSelect from '~/components/cell/SingleSelect.vue'
2 years ago
import MultiSelect from '~/components/cell/MultiSelect.vue'
import DatePicker from '~/components/cell/DatePicker.vue'
import YearPicker from '~/components/cell/YearPicker.vue'
import DateTimePicker from '~/components/cell/DateTimePicker.vue'
import TimePicker from '~/components/cell/TimePicker.vue'
import Rating from '~/components/cell/Rating.vue'
import Duration from '~/components/cell/Duration.vue'
import Percent from '~/components/cell/Percent.vue'
import Currency from '~/components/cell/Currency.vue'
import Decimal from '~/components/cell/Decimal.vue'
import Integer from '~/components/cell/Integer.vue'
import Float from '~/components/cell/Float.vue'
import Text from '~/components/cell/Text.vue'
interface Props {
column: ColumnType
filter: Filter
}
interface Emits {
(event: 'updateFilterValue', model: any): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const column = toRef(props, 'column')
const editEnabled = ref(true)
provide(ColumnInj, column)
provide(EditModeInj, readonly(editEnabled))
provide(ReadonlyInj, ref(false))
const checkTypeFunctions = {
isSingleSelect,
isMultiSelect,
isDate,
isYear,
isDateTime,
isTime,
isRating,
isDuration,
isPercent,
isCurrency,
isDecimal,
isInt,
isFloat,
isTextArea,
}
type FilterType = keyof typeof checkTypeFunctions
2 years ago
const { sqlUi } = $(useProject())
const abstractType = $computed(() => (column.value?.dt && sqlUi ? sqlUi.getAbstractType(column.value) : null))
2 years ago
const checkType = (filterType: FilterType) => {
const checkTypeFunction = checkTypeFunctions[filterType]
2 years ago
if (!column.value || !checkTypeFunction) {
return false
}
2 years ago
return checkTypeFunction(column.value, abstractType)
}
const filterInput = computed({
get: () => {
return props.filter.value
},
set: (value) => {
emit('updateFilterValue', value)
},
})
const booleanOptions = [
{ value: true, label: 'true' },
{ value: false, label: 'false' },
{ value: null, label: 'unset' },
]
const componentMap: Partial<Record<FilterType, any>> = $computed(() => {
return {
// use MultiSelect for SingleSelect columns for anyof / nanyof filters
isSingleSelect: ['anyof', 'nanyof'].includes(props.filter.comparison_op!) ? MultiSelect : SingleSelect,
isMultiSelect: MultiSelect,
isDate: ['daysAgo', 'daysFromNow', 'pastNumberOfDays', 'nextNumberOfDays'].includes(props.filter.comparison_sub_op!)
? Decimal
: DatePicker,
isYear: YearPicker,
isDateTime: ['daysAgo', 'daysFromNow', 'pastNumberOfDays', 'nextNumberOfDays'].includes(props.filter.comparison_sub_op!)
? Decimal
: DateTimePicker,
isTime: TimePicker,
isRating: Rating,
isDuration: Duration,
isPercent: Percent,
isCurrency: Currency,
isDecimal: Decimal,
isInt: Integer,
isFloat: Float,
}
})
const filterType = $computed(() => {
return Object.keys(componentMap).find((key) => checkType(key as FilterType))
})
2 years ago
const componentProps = $computed(() => {
switch (filterType) {
case 'isSingleSelect':
case 'isMultiSelect': {
return { disableOptionCreation: true }
}
case 'isPercent':
case 'isDecimal':
case 'isFloat':
case 'isInt': {
return { class: 'h-32px' }
}
case 'isDuration': {
return { showValidationError: false }
}
default: {
return {}
}
}
2 years ago
})
const hasExtraPadding = $computed(() => {
return (
2 years ago
column.value &&
(isInt(column.value, abstractType) ||
isDate(column.value, abstractType) ||
isDateTime(column.value, abstractType) ||
isTime(column.value, abstractType) ||
isYear(column.value, abstractType))
)
})
</script>
<template>
<a-select
v-if="column && isBoolean(column, abstractType)"
v-model:value="filterInput"
:disabled="filter.readOnly"
:options="booleanOptions"
/>
2 years ago
<div
v-else
class="bg-white border-1 flex min-w-120px max-w-170px min-h-32px h-full"
:class="{ 'px-2': hasExtraPadding }"
@mouseup.stop
>
<component
:is="filterType ? componentMap[filterType] : Text"
v-model="filterInput"
:disabled="filter.readOnly"
placeholder="Enter a value"
:column="column"
2 years ago
class="flex"
v-bind="componentProps"
/>
</div>
</template>