Skip to content

Conversation

@carbonFibreCode
Copy link
Contributor

@carbonFibreCode carbonFibreCode commented Jan 28, 2026

Fixes: twentyhq/core-team-issues#2027

We've replaced the DATE_TIME picker with DATE picker, and changed the logic to filter for complete day period.

Screen.Recording.2026-01-29.at.4.56.06.AM.mov

@github-actions
Copy link
Contributor

github-actions bot commented Jan 28, 2026

TODOs/FIXMEs:

  • // TODO: check if we need to put workspace member timezone here: packages/twenty-server/src/engine/metadata-modules/view/services/view-query-params.service.ts

Generated by 🚫 dangerJS against 6552e9c

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 28, 2026

Greptile Overview

Greptile Summary

Changed DATE_TIME filter with IS operand to use date-only picker and filter for entire day period instead of precise minute.

Key Changes:

  • Frontend now displays DatePicker instead of DateTimePicker when IS operand is selected for DATE_TIME fields
  • Filter logic updated to match entire day (00:00 to 23:59:59.999) in user's timezone rather than a single minute
  • Server now retrieves and passes workspace member timezone to filter logic instead of hardcoded UTC
  • Both plain date (2027-01-15) and instant (2027-01-15T00:00:00Z) formats are now handled correctly

Issues Found:

  • Syntax error in ObjectFilterDropdownDateInput.tsx line 48: incorrect toZonedDateTime API usage with object parameter instead of direct timezone string

Confidence Score: 4/5

  • Safe to merge after fixing the syntax error in ObjectFilterDropdownDateInput.tsx
  • The PR successfully addresses the issue of filtering by full day period for DATE_TIME fields. The logic is sound and consistently implemented across frontend, backend, and shared utilities. However, there's a syntax error that needs correction before merge.
  • packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx requires immediate attention due to incorrect API usage

Important Files Changed

Filename Overview
packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx Replaced DATE_TIME picker with DATE picker for IS operand; potential API issue with toZonedDateTime call
packages/twenty-server/src/engine/metadata-modules/view/services/view-query-params.service.ts Added workspace member timezone lookup and pass to filter value dependencies instead of hardcoded UTC
packages/twenty-shared/src/utils/filter/turnRecordFilterIntoGqlOperationFilter.ts Updated DATE_TIME IS operand to filter for entire day period using user timezone instead of precise minute

Sequence Diagram

sequenceDiagram
    participant User
    participant DateInput as ObjectFilterDropdownDateInput
    participant FilterInput as ObjectFilterDropdownFilterInput
    participant Backend as view-query-params.service
    participant Filter as turnRecordFilterIntoGqlOperationFilter
    participant DB as Database

    User->>FilterInput: Select DATE_TIME field with IS operand
    FilterInput->>DateInput: Render DatePicker (not DateTimePicker)
    User->>DateInput: Select date (e.g., 2027-01-15)
    DateInput->>DateInput: Convert to Instant at 00:00 in user timezone
    DateInput->>Backend: Save filter with Instant value
    
    Note over User,DB: Later: Apply saved view filter
    
    User->>Backend: Load view
    Backend->>Backend: Fetch workspace member timezone
    Backend->>Filter: Pass filter with timezone dependency
    Filter->>Filter: Detect plain date or instant format
    Filter->>Filter: Calculate day start and end in user timezone
    Filter->>DB: Query with gte (day start) and lt (day end)
    DB->>User: Return records from full day period
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

}

const newFilterValue = Temporal.PlainDate.from(newPlainDate)
.toZonedDateTime({ timeZone, plainTime: '00:00' })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

incorrect API usage - toZonedDateTime accepts timezone string directly, not an object

Suggested change
.toZonedDateTime({ timeZone, plainTime: '00:00' })
.toZonedDateTime(timeZone)
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx
Line: 48:48

Comment:
incorrect API usage - `toZonedDateTime` accepts timezone string directly, not an object

```suggestion
      .toZonedDateTime(timeZone)
```

How can I resolve this? If you propose a fix, please make it concise.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 28, 2026

🚀 Preview Environment Ready!

Your preview environment is available at: http://bore.pub:22992

This environment will automatically shut down when the PR is closed or after 5 hours.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 6 files

@lucasbordeau
Copy link
Contributor

lucasbordeau commented Jan 29, 2026

The approach is good.

But instead of having two code paths to handle both a plain date and a date time value, we want to only handle plain date values for DATE_TIME + IS operand.

We'll create a migration command to migrate any date time string to a plain date string value in core.viewFilter table.

Let's take for granted in your code that viewFilter.value contains a plain date string.

Also during your QA, be careful with operand change, because sometimes changing an operand and keeping the value associated to a previous operand can provoke a crash, we have to take care of cleaning up the value for any operand change.

@lucasbordeau
Copy link
Contributor

lucasbordeau commented Jan 29, 2026

If you are willing to work on this simple migration command you can do it in another PR, otherwise I'll do it no problem.

@lucasbordeau lucasbordeau changed the title [Fix]: 2027 date time is operand Allow DATE_TIME IS operand to filter on a whole day Jan 29, 2026
@carbonFibreCode
Copy link
Contributor Author

Ohk sure I'll do it in another PR.


let timeZone = 'UTC';

if (currentWorkspaceMemberId) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you put this into a util or separate function in this service ? getWorkspaceMemberTimezoneIfAvailable for example

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 6 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/twenty-front/src/modules/object-record/record-filter/hooks/useGetRecordFilterDisplayValue.ts">

<violation number="1" location="packages/twenty-front/src/modules/object-record/record-filter/hooks/useGetRecordFilterDisplayValue.ts:97">
P2: DATE_TIME IS display now always uses Temporal.PlainDate.from, which throws on stored ISO datetimes with timezone offsets (e.g., existing values like "2024-09-17T20:46:58.922Z"), causing a runtime error and broken filter UI for legacy values.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment on lines 97 to 101
const zonedDateTime = Temporal.PlainDate.from(
recordFilter.value,
).toZonedDateTime(userTimezone);
const { displayValue } = getDateFilterDisplayValue(zonedDateTime);
return `${displayValue}`;
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: DATE_TIME IS display now always uses Temporal.PlainDate.from, which throws on stored ISO datetimes with timezone offsets (e.g., existing values like "2024-09-17T20:46:58.922Z"), causing a runtime error and broken filter UI for legacy values.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/twenty-front/src/modules/object-record/record-filter/hooks/useGetRecordFilterDisplayValue.ts, line 97:

<comment>DATE_TIME IS display now always uses Temporal.PlainDate.from, which throws on stored ISO datetimes with timezone offsets (e.g., existing values like "2024-09-17T20:46:58.922Z"), causing a runtime error and broken filter UI for legacy values.</comment>

<file context>
@@ -92,28 +94,11 @@ export const useGetRecordFilterDisplayValue = () => {
-            const { displayValue } = getDateFilterDisplayValue(zonedDateTime);
-            return `${displayValue}`;
-          }
+          const zonedDateTime = Temporal.PlainDate.from(
+            recordFilter.value,
+          ).toZonedDateTime(userTimezone);
</file context>
Suggested change
const zonedDateTime = Temporal.PlainDate.from(
recordFilter.value,
).toZonedDateTime(userTimezone);
const { displayValue } = getDateFilterDisplayValue(zonedDateTime);
return `${displayValue}`;
let zonedDateTime: Temporal.ZonedDateTime;
try {
zonedDateTime = Temporal.PlainDate.from(
recordFilter.value,
).toZonedDateTime(userTimezone);
} catch {
zonedDateTime = Temporal.Instant.from(
recordFilter.value,
).toZonedDateTimeISO(userTimezone);
}
const { displayValue } = getDateFilterDisplayValue(zonedDateTime);
return `${displayValue}`;
Fix with Cubic

Copy link
Contributor

@lucasbordeau lucasbordeau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice PR

Copilot AI review requested due to automatic review settings February 4, 2026 06:02
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR modifies the DATE_TIME filter with the IS operand to filter on whole days instead of minute-level precision. The change replaces the DATE_TIME picker with a DATE picker for the IS operand and adjusts the filtering logic to cover a complete 24-hour period in the user's timezone.

Changes:

  • Modified filtering logic to convert DATE_TIME IS filters to use full-day ranges based on user timezone
  • Added timezone retrieval from workspace member settings with UTC fallback
  • Updated frontend components to show date picker instead of datetime picker for IS operand
  • Implemented value conversion logic when switching between IS and other operands

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/twenty-shared/src/utils/filter/turnRecordFilterIntoGqlOperationFilter.ts Changed DATE_TIME IS operand logic from 1-minute window to 24-hour window using PlainDate and user timezone
packages/twenty-server/src/engine/metadata-modules/view/services/view-query-params.service.ts Added workspace member timezone retrieval and passed it to filter computation
packages/twenty-server/src/engine/metadata-modules/view/services/tests/view-query-params.service.spec.ts Updated test mock to include GlobalWorkspaceOrmManager dependency
packages/twenty-server/src/engine/metadata-modules/view/constants/default-timezone.constant.ts Created constant for default UTC timezone fallback
packages/twenty-front/src/modules/object-record/record-filter/hooks/useGetRecordFilterDisplayValue.ts Updated display value logic to show date format for DATE_TIME IS operand
packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useGetInitialFilterValue.ts Modified initial value generation for DATE_TIME IS to use PlainDate format
packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand.ts Added conversion logic for switching between IS and other operands, handling format changes between PlainDate and Instant
packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput.tsx Added conditional rendering to show date picker for DATE_TIME IS operand
packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx Improved null handling and variable naming for date input

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

auto-merge was automatically disabled February 4, 2026 17:27

Head branch was pushed to by a user without write access

@carbonFibreCode
Copy link
Contributor Author

@lucasbordeau I’ve addressed the CI failure by fixing the failing test; could you please re-enable auto-merge on this pull request when you have a moment?

@lucasbordeau
Copy link
Contributor

@carbonFibreCode I want to be sure of the strategy to roll this out before, because there is a data migration involved.

Copy link
Contributor

@lucasbordeau lucasbordeau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Waiting for deploy strategy

@carbonFibreCode
Copy link
Contributor Author

@carbonFibreCode I want to be sure of the strategy to roll this out before, because there is a data migration involved.

@lucasbordeau ohh yes, we have two PRs for the issue , and both are dependent on each other.

@lucasbordeau
Copy link
Contributor

lucasbordeau commented Feb 5, 2026

We will use a feature flag.

So here are the requirements for both PR.

This PR :

  • Add a feature flag to enable this feature, set it to false by default (but true in the dev seeds)

The data migration PR :

  • The feature flag should be set to true right after the migration, in the same function.
  • Be careful to flush the cache in the data migration also

Comment on lines +393 to +397
if (recordFilter.operand === RecordFilterOperand.IS) {
const timeZone = filterValueDependencies.timeZone ?? 'UTC';
const plainDate = Temporal.PlainDate.from(recordFilter.value);
const zonedDateTime = plainDate.toZonedDateTime(timeZone);
const start = zonedDateTime.toInstant();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The backend unconditionally parses DATE_TIME IS filter values as PlainDate, but the frontend can send Instant format, causing a crash if a feature flag is disabled.
Severity: HIGH

Suggested Fix

The backend should be made resilient to both PlainDate and Instant formats for DATE_TIME IS filters to ensure backwards compatibility. This can be achieved by attempting to parse the value as a PlainDate first, and if that fails, falling back to parsing it as an Instant.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location:
packages/twenty-shared/src/utils/filter/turnRecordFilterIntoGqlOperationFilter.ts#L393-L397

Potential issue: The backend code at `turnRecordFilterIntoGqlOperationFilter.ts`
unconditionally assumes that when a `DATE_TIME` filter has the `IS` operand, the filter
value is in `PlainDate` format (e.g., 'YYYY-MM-DD'). However, the frontend conditionally
generates this format only when the `IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED` feature flag
is enabled. If this flag is disabled, the frontend generates a value in `Instant` format
(an ISO 8601 timestamp). This mismatch will cause the backend to throw an unhandled
`RangeError` when `Temporal.PlainDate.from()` receives an `Instant` string, crashing the
request. This affects not only newly created filters but also any existing saved filters
that were created in the `Instant` format before this change.

@carbonFibreCode
Copy link
Contributor Author

carbonFibreCode commented Feb 6, 2026

@lucasbordeau done with feature flags, Please let me know further updates regarding the deployment strategy for this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DATE_TIME IS operand should filter on plain date for user timezone, like DATE.

3 participants