Skip to content

Commit c06f5de

Browse files
fix(profiles): review fixes — operators, profile.* filters, count/list parity
Addresses the cloud + CodeRabbit review findings on the profiles filter: - All 15 filter operators (doesNotContain/startsWith/endsWith/regex/gt/lt/ gte/lte/isNull/isNotNull/…) via a shared operatorClause, in the v2, events and profile-property builders. Was: everything unhandled fell through to IN (e.g. doesNotContain returned the opposite audience). - profile.* filters (profile.id / profile.properties.*) now apply to the outer profiles query instead of being dropped — "did event X AND profile.id=Y" now actually filters by id (was returning all profiles). - Count/list parity: behavioural list no longer gates profiles.created_at (first-seen) by the window — the event subquery bounds time — so the count and rows agree (was 152 vs 8). Count now mirrors the list (behavioural membership + profile.* filters + search + window) via a shared subquery. - Pagination: offset = cursor (client already sends the row offset); removes the (page-1)*take*take that made page 2+ empty. - START_DATE guard: validate/anchor to UTC so a blank/garbled env falls back instead of silently disabling the coverage gate; parse queryStart as UTC too. - Nits: count input is a plain typed field (no spinner, no decimals → no 400); LastSeenPicker restores the time toggle on reopen; drop unused imports; fix a stale transformProfile comment.
1 parent 23e838f commit c06f5de

4 files changed

Lines changed: 266 additions & 171 deletions

File tree

apps/start/src/components/profiles/event-count-filter.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,28 @@ export function EventCountFilter({
5252
))}
5353
</select>
5454
<input
55-
type="number"
56-
min={0}
55+
type="text"
56+
inputMode="numeric"
5757
value={value}
58-
onChange={(e) => onValueChange(Math.max(0, Number(e.target.value) || 0))}
58+
onChange={(e) =>
59+
onValueChange(
60+
Math.max(0, Number(e.target.value.replace(/[^0-9]/g, '')) || 0),
61+
)
62+
}
5963
className={inputCls}
6064
aria-label="Number of times"
6165
/>
6266
{isRange && (
6367
<>
6468
<span>and</span>
6569
<input
66-
type="number"
67-
min={0}
70+
type="text"
71+
inputMode="numeric"
6872
value={value2}
6973
onChange={(e) =>
70-
onValue2Change(Math.max(0, Number(e.target.value) || 0))
74+
onValue2Change(
75+
Math.max(0, Number(e.target.value.replace(/[^0-9]/g, '')) || 0),
76+
)
7177
}
7278
className={inputCls}
7379
aria-label="Upper bound"

apps/start/src/components/profiles/last-seen-picker.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,19 @@ export function LastSeenPicker({
7373

7474
const sync = () => {
7575
setMode(startDate && !endDate ? 'since' : 'fixed');
76-
setFrom(parseDb(startDate));
77-
setTo(parseDb(endDate));
76+
const f = parseDb(startDate);
77+
const t = parseDb(endDate);
78+
setFrom(f);
79+
setTo(t);
80+
// Restore the time toggle from the incoming bounds — otherwise reopening a
81+
// saved hour-precise window shows date-only fields and Apply silently widens
82+
// it to full days (00:00:00 / 23:59:59).
83+
const startHasTime =
84+
!!f && (f.getHours() !== 0 || f.getMinutes() !== 0 || f.getSeconds() !== 0);
85+
const endHasTime =
86+
!!t &&
87+
!(t.getHours() === 23 && t.getMinutes() === 59 && t.getSeconds() === 59);
88+
setEnableTime(startHasTime || endHasTime);
7889
};
7990

8091
const canApply = mode === 'fixed' ? !!from && !!to : !!from;

apps/start/src/components/profiles/table/columns.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import { ProjectLink } from '@/components/links';
22
import { SerieIcon } from '@/components/report-chart/common/serie-icon';
33
import { useProfilesSort } from '@/hooks/use-profiles-sort';
4-
import { formatDateTime, formatTime } from '@/utils/date';
54
import { getProfileName } from '@/utils/getters';
65
import type { ColumnDef } from '@tanstack/react-table';
7-
import { isToday } from 'date-fns';
86
import { ArrowDownIcon, ArrowUpIcon } from 'lucide-react';
97

108
import type { IServiceProfile } from '@openpanel/db';

0 commit comments

Comments
 (0)