Browse Source

use cell inputs for filters input type

pull/4425/head
Ekaterina Balakina 2 years ago
parent
commit
2287ae6581
  1. 25
      packages/nc-gui/components/smartsheet/toolbar/ColumnFilter.vue
  2. 159
      packages/nc-gui/components/smartsheet/toolbar/FilterInput.vue
  3. 2
      tests/playwright/pages/Dashboard/WebhookForm/index.ts
  4. 4
      tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts

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

@ -100,6 +100,15 @@ watch(
},
)
const getColumn = (filter: Filter) => {
return columns.value?.find((col) => col.id === filter.fk_column_id)
}
const selectFilterField = (filter: Filter, index: number) => {
filter.value = null
saveOrUpdate(filter, index)
}
const applyChanges = async (hookId?: string, _nested = false) => {
await sync(hookId, _nested)
@ -198,7 +207,7 @@ defineExpose({
:columns="columns"
:disabled="filter.readOnly"
@click.stop
@change="saveOrUpdate(filter, i)"
@change="selectFilterField(filter, i)"
/>
<a-select
@ -231,14 +240,18 @@ defineExpose({
@change="saveOrUpdate(filter, i)"
/>
<a-input
<LazySmartsheetToolbarFilterInput
v-else
:key="`${i}_7`"
v-model:value="filter.value"
class="nc-filter-value-select"
:disabled="filter.readOnly"
:column="getColumn(filter)"
:filter="filter"
@updateFilterValue="
(value) => {
filter.value = value
saveOrUpdate(filter, i)
}
"
@click.stop
@input="saveOrUpdate(filter, i)"
/>
</template>
</template>

159
packages/nc-gui/components/smartsheet/toolbar/FilterInput.vue

@ -0,0 +1,159 @@
<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'
import MultiSelect from '~/components/cell/MultiSelect'
import DatePicker from '~/components/cell/DatePicker'
import YearPicker from '~/components/cell/YearPicker'
import DateTimePicker from '~/components/cell/DateTimePicker'
import TimePicker from '~/components/cell/TimePicker'
import Rating from '~/components/cell/Rating'
import Duration from '~/components/cell/Duration'
import Percent from '~/components/cell/Percent'
import Currency from '~/components/cell/Currency'
import Decimal from '~/components/cell/Decimal'
import Integer from '~/components/cell/Integer'
import Float from '~/components/cell/Float'
import Text from '~/components/cell/Text'
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
const { sqlUi } = useProject()
const abstractType = $computed(() => column.value && sqlUi.value.getAbstractType(column.value))
const checkType = (type: FilterType) => {
if (!column.value) {
return false
}
const checkTypeFunction = checkTypeFunctions[type]
if (!checkTypeFunction) {
return false
}
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 & 'default', any>> = {
isSingleSelect: SingleSelect,
isMultiSelect: MultiSelect,
isDate: DatePicker,
isYear: YearPicker,
isDateTime: 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))
})
const isNumeric = $computed(() => {
if (!column.value) {
return false
}
return (
isPercent(column.value) || isInt(column.value, abstractType) || isDecimal(column.value) || isFloat(column.value, abstractType)
)
})
</script>
<template>
<a-select
v-if="column && isBoolean(column, abstractType)"
v-model:value="filterInput"
:disabled="filter.readOnly"
:options="booleanOptions"
/>
<div v-else class="bg-white border-1 flex min-w-120px max-w-170px min-h-32px h-full px-2" @mouseup.stop>
<component
:is="filterType ? componentMap[filterType] : Text"
v-model="filterInput"
:disabled="filter.readOnly"
:column="column"
:class="{ 'h-32px': isNumeric }"
/>
</div>
</template>

2
tests/playwright/pages/Dashboard/WebhookForm/index.ts

@ -87,7 +87,7 @@ export class WebhookFormPage extends BasePage {
await this.rootPage.waitForTimeout(1500);
if (operator != 'is null' && operator != 'is not null') {
await modal.locator('input.nc-filter-value-select').fill(value);
await modal.locator('.nc-filter-value-select > input').fill(value);
}
if (save) {

4
tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts

@ -18,7 +18,7 @@ export class ToolbarFilterPage extends BasePage {
await expect(this.get().locator('.nc-filter-field-select').nth(index)).toHaveText(column);
await expect(this.get().locator('.nc-filter-operation-select').nth(index)).toHaveText(operator);
await expect
.poll(async () => await this.get().locator('input.nc-filter-value-select').nth(index).inputValue())
.poll(async () => await this.get().locator('.nc-filter-value-select > input').nth(index).inputValue())
.toBe(value);
}
@ -70,7 +70,7 @@ export class ToolbarFilterPage extends BasePage {
await this.toolbar.parent.dashboard.waitForLoaderToDisappear();
}
const fillFilter = this.rootPage.locator('.nc-filter-value-select').last().fill(value);
const fillFilter = this.rootPage.locator('.nc-filter-value-select > input').last().fill(value);
await this.waitForResponse({
uiAction: fillFilter,
httpMethodsToMatch: ['GET'],

Loading…
Cancel
Save