From b6787c6fcd3d0c56ce04941d239774714845010e Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Mon, 23 Jun 2025 17:15:30 +0200 Subject: [PATCH] Record filter `greaterThan` becomes inclusive as `lowerThan` (#12786) # Introduction Greater than filtering wasn't inclusive whereas lower than was, resulting in sending empty array to filtering resolver Also refactored the transpilation methods to avoid asserting on the `RATING_VALUES` order closes https://github.com/twentyhq/twenty/issues/12779 --- .../ObjectFilterDropdownRatingInput.tsx | 32 ++++++++++--------- .../types/guards/isFieldRatingValue.ts | 7 ++-- ...etSpreadSheetFieldValidationDefinitions.ts | 7 ++-- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRatingInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRatingInput.tsx index 7378eb993..1c9db8ef4 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRatingInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRatingInput.tsx @@ -5,6 +5,7 @@ import { RatingInput } from '@/ui/field/input/components/RatingInput'; import { useApplyObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue'; import { useObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useObjectFilterDropdownFilterValue'; import styled from '@emotion/styled'; +import { isDefined } from 'twenty-shared/utils'; const StyledRatingInputContainer = styled.div` padding: ${({ theme }) => theme.spacing(2)}; @@ -12,25 +13,24 @@ const StyledRatingInputContainer = styled.div` const convertFieldRatingValueToNumber = ( rating: Exclude, -): string => { - return rating.split('_')[1]; -}; +): string => rating.split('_')[1]; export const convertGreaterThanRatingToArrayOfRatingValues = ( greaterThanValue: number, -) => { - return RATING_VALUES.filter((_, index) => index + 1 > greaterThanValue); -}; +) => + RATING_VALUES.filter( + (ratingValue) => +ratingValue.split('_')[1] >= greaterThanValue, + ); export const convertLessThanRatingToArrayOfRatingValues = ( lessThanValue: number, -) => { - return RATING_VALUES.filter((_, index) => index + 1 <= lessThanValue); -}; +) => + RATING_VALUES.filter( + (ratingValue) => +ratingValue.split('_')[1] <= lessThanValue, + ); -export const convertRatingToRatingValue = (rating: number) => { - return `RATING_${rating}` as FieldRatingValue; -}; +export const convertRatingToRatingValue = (rating: number) => + `RATING_${rating}` as FieldRatingValue; export const ObjectFilterDropdownRatingInput = () => { const { applyObjectFilterDropdownFilterValue } = @@ -50,9 +50,11 @@ export const ObjectFilterDropdownRatingInput = () => { applyObjectFilterDropdownFilterValue(ratingValueConverted); }; - const currentFilterValueConvertedToRatingValue = convertRatingToRatingValue( - Number(objectFilterDropdownFilterValue), - ); + const currentFilterValueConvertedToRatingValue = isDefined( + objectFilterDropdownFilterValue, + ) + ? convertRatingToRatingValue(Number(objectFilterDropdownFilterValue)) + : null; return ( diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRatingValue.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRatingValue.ts index 3fc8459a0..71b721578 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRatingValue.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRatingValue.ts @@ -1,11 +1,8 @@ -import { z } from 'zod'; - import { RATING_VALUES } from '@/object-record/record-field/meta-types/constants/RatingValues'; import { FieldRatingValue } from '../FieldMetadata'; -const ratingSchema = z.string().pipe(z.enum(RATING_VALUES)); - export const isFieldRatingValue = ( fieldValue: unknown, -): fieldValue is FieldRatingValue => ratingSchema.safeParse(fieldValue).success; +): fieldValue is FieldRatingValue => + RATING_VALUES.includes(fieldValue as NonNullable); diff --git a/packages/twenty-front/src/modules/object-record/spreadsheet-import/utils/getSpreadSheetFieldValidationDefinitions.ts b/packages/twenty-front/src/modules/object-record/spreadsheet-import/utils/getSpreadSheetFieldValidationDefinitions.ts index b3aadea9c..2d25daa24 100644 --- a/packages/twenty-front/src/modules/object-record/spreadsheet-import/utils/getSpreadSheetFieldValidationDefinitions.ts +++ b/packages/twenty-front/src/modules/object-record/spreadsheet-import/utils/getSpreadSheetFieldValidationDefinitions.ts @@ -1,4 +1,5 @@ import { RATING_VALUES } from '@/object-record/record-field/meta-types/constants/RatingValues'; +import { isFieldRatingValue } from '@/object-record/record-field/types/guards/isFieldRatingValue'; import { emailSchema } from '@/object-record/record-field/validation-schemas/emailSchema'; import { SpreadsheetImportFieldValidationDefinition } from '@/spreadsheet-import/types'; import { t } from '@lingui/core/macro'; @@ -221,11 +222,7 @@ export const getSpreadSheetFieldValidationDefinitions = ( return [ { rule: 'function', - isValid: (value: string) => { - return RATING_VALUES.includes( - value as (typeof RATING_VALUES)[number], - ); - }, + isValid: isFieldRatingValue, errorMessage: `${fieldName} ${t` must be one of ${ratingValues} values`}`, level: 'error', },