diff --git a/mathesar_ui/src/components/cell-fabric/data-types/string.ts b/mathesar_ui/src/components/cell-fabric/data-types/string.ts index 3711fa67c8..942f119d00 100644 --- a/mathesar_ui/src/components/cell-fabric/data-types/string.ts +++ b/mathesar_ui/src/components/cell-fabric/data-types/string.ts @@ -38,6 +38,12 @@ const stringType: CellComponentFactory = { }, }; }, + getFilterInput: (column: Column): ComponentAndProps => ({ + component: TextInput, + props: { + maxlength: optionalNonNullable(column.type_options?.length), + }, + }), getDisplayFormatter: () => String, }; diff --git a/mathesar_ui/src/components/cell-fabric/data-types/typeDefinitions.ts b/mathesar_ui/src/components/cell-fabric/data-types/typeDefinitions.ts index c078d011fe..0f023a8ee6 100644 --- a/mathesar_ui/src/components/cell-fabric/data-types/typeDefinitions.ts +++ b/mathesar_ui/src/components/cell-fabric/data-types/typeDefinitions.ts @@ -27,14 +27,38 @@ export type CellDataType = SimpleCellDataTypes | CompoundCellDataTypes; export interface CellComponentFactory { initialInputValue?: unknown; + + /** + * Get the component used to render the cell + */ get( column: CellColumnLike, config?: Record, ): ComponentAndProps; + + /** Get the component used to render an input when the user is adding or + * editing a value of this type. This is used on the record page, and default + * value, for example. + */ getInput( column: CellColumnLike, config?: Record, ): ComponentAndProps; + + /** + * Implement this method in order to customize the input used within filter + * conditions. If not implemented, then we fall back to using the `getInput` + * method. Custom filter input components are useful when we want slightly + * different behavior for searching vs data entry. See [issue #4052][4052] for + * an example. + * + * [4052]: https://github.com/mathesar-foundation/mathesar/issues/4052 + */ + getFilterInput?( + column: CellColumnLike, + config?: Record, + ): ComponentAndProps; + getDisplayFormatter( column: CellColumnLike, config?: Record, diff --git a/mathesar_ui/src/components/cell-fabric/utils.ts b/mathesar_ui/src/components/cell-fabric/utils.ts index f4356e141c..54c5fbcd88 100644 --- a/mathesar_ui/src/components/cell-fabric/utils.ts +++ b/mathesar_ui/src/components/cell-fabric/utils.ts @@ -69,6 +69,20 @@ export function getDbTypeBasedInputCap( return DataTypes[cellInfo?.type ?? 'string'].getInput(column, config); } +export function getDbTypeBasedFilterCap( + column: CellColumnLike, + fkTargetTableId?: Table['oid'], + optionalCellInfo?: CellInfo, +): ComponentAndProps { + const cellInfo = optionalCellInfo ?? getCellInfo(column.type); + const factory = DataTypes[cellInfo?.type ?? 'string']; + if (factory.getFilterInput) { + const config = getCellConfiguration(column.type, cellInfo); + return factory.getFilterInput(column, config); + } + return getDbTypeBasedInputCap(column, fkTargetTableId, cellInfo); +} + export function getInitialInputValue( column: CellColumnLike, fkTargetTableId?: Table['oid'], diff --git a/mathesar_ui/src/components/filter-entry/FilterEntry.svelte b/mathesar_ui/src/components/filter-entry/FilterEntry.svelte index 578ae353c7..59217cfbe4 100644 --- a/mathesar_ui/src/components/filter-entry/FilterEntry.svelte +++ b/mathesar_ui/src/components/filter-entry/FilterEntry.svelte @@ -4,7 +4,7 @@ import type { ConstraintType } from '@mathesar/api/rpc/constraints'; import DynamicInput from '@mathesar/components/cell-fabric/DynamicInput.svelte'; - import { getDbTypeBasedInputCap } from '@mathesar/components/cell-fabric/utils'; + import { getDbTypeBasedFilterCap } from '@mathesar/components/cell-fabric/utils'; import ColumnName from '@mathesar/components/column/ColumnName.svelte'; import { iconDeleteMajor } from '@mathesar/icons'; import type { @@ -69,7 +69,7 @@ $: selectedCondition = conditionIdentifier ? selectedColumnFiltersMap.get(conditionIdentifier) : undefined; - $: selectedColumnInputCap = selectedColumn?.inputComponentAndProps; + $: selectedColumnInputCap = selectedColumn?.filterComponentAndProps; const initialNoOfFilters = numberOfFilters; let showError = false; @@ -154,7 +154,7 @@ if (abstractTypeId === parameterTypeId && selectedColumnInputCap) { return selectedColumnInputCap; } - return getDbTypeBasedInputCap({ + return getDbTypeBasedFilterCap({ type: parameterTypeId, type_options: {}, metadata: {}, diff --git a/mathesar_ui/src/components/filter-entry/types.ts b/mathesar_ui/src/components/filter-entry/types.ts index 63a174e834..c7d3d461b6 100644 --- a/mathesar_ui/src/components/filter-entry/types.ts +++ b/mathesar_ui/src/components/filter-entry/types.ts @@ -7,5 +7,5 @@ export interface FilterEntryColumnLike extends Pick { abstractType: AbstractType; allowedFiltersMap: ReturnType; - inputComponentAndProps: ComponentAndProps; + filterComponentAndProps: ComponentAndProps; } diff --git a/mathesar_ui/src/stores/table-data/processedColumns.ts b/mathesar_ui/src/stores/table-data/processedColumns.ts index e797cf8ae0..313696bbde 100644 --- a/mathesar_ui/src/stores/table-data/processedColumns.ts +++ b/mathesar_ui/src/stores/table-data/processedColumns.ts @@ -5,6 +5,7 @@ import type { Constraint } from '@mathesar/api/rpc/constraints'; import type { CellColumnFabric } from '@mathesar/components/cell-fabric/types'; import { getCellCap, + getDbTypeBasedFilterCap, getDbTypeBasedInputCap, getDisplayFormatter, getInitialInputValue, @@ -40,6 +41,7 @@ export interface ProcessedColumn extends CellColumnFabric { abstractType: AbstractType; initialInputValue: unknown; inputComponentAndProps: ComponentAndProps; + filterComponentAndProps: ComponentAndProps; allowedFiltersMap: ReturnType; preprocFunctions: AbstractTypePreprocFunctionDefinition[]; formatCellValue: ( @@ -110,6 +112,11 @@ export function processColumn({ fkTargetTableId, abstractType.cellInfo, ), + filterComponentAndProps: getDbTypeBasedFilterCap( + column, + fkTargetTableId, + abstractType.cellInfo, + ), allowedFiltersMap: retrieveFilters(abstractType.identifier, linkFk), preprocFunctions: getPreprocFunctionsForAbstractType( abstractType.identifier, diff --git a/mathesar_ui/src/systems/data-explorer/utils.ts b/mathesar_ui/src/systems/data-explorer/utils.ts index cb2c07c862..870f988291 100644 --- a/mathesar_ui/src/systems/data-explorer/utils.ts +++ b/mathesar_ui/src/systems/data-explorer/utils.ts @@ -11,6 +11,7 @@ import type { JoinPath, JoinableTablesResult } from '@mathesar/api/rpc/tables'; import type { CellColumnFabric } from '@mathesar/components/cell-fabric/types'; import { getCellCap, + getDbTypeBasedFilterCap, getDbTypeBasedInputCap, getDisplayFormatter, getInitialInputValue, @@ -47,6 +48,7 @@ export interface ProcessedQueryResultColumn extends CellColumnFabric { column: QueryResultColumn; abstractType: AbstractType; inputComponentAndProps: ComponentAndProps; + filterComponentAndProps: ComponentAndProps; initialInputValue: unknown; allowedFiltersMap: ReturnType; preprocFunctions: AbstractTypePreprocFunctionDefinition[]; @@ -368,6 +370,11 @@ function processColumn( undefined, abstractType.cellInfo, ), + filterComponentAndProps: getDbTypeBasedFilterCap( + column, + undefined, + abstractType.cellInfo, + ), initialInputValue: getInitialInputValue( column, undefined,