Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
c1b8292
feat: add support for `scheduleStartAt` and `scheduleOffsetMinutes` i…
melsalcedo Feb 9, 2026
ffa5bf2
Update packages/api/src/controllers/alerts.ts
mlsalcedo Feb 17, 2026
7f1506c
Update packages/api/src/controllers/alerts.ts
mlsalcedo Feb 17, 2026
8408688
refactor: simplify `scheduleStartAt` validation using `fns.isValid` f…
melsalcedo Feb 17, 2026
bf4b847
feat: improve alert scheduling by updating `scheduleStartAt` validati…
melsalcedo Feb 17, 2026
799c84c
Merge branch 'main' into startTime-offset
teeohhem Feb 19, 2026
03c07cb
refactor(alerts): dedupe interval and offset validation
melsalcedo Feb 19, 2026
f8b379e
feat(app): use DateTimePicker for scheduleStartAt input
melsalcedo Feb 20, 2026
ea4ab24
feat(app): add datetime picker to dashboard alert start time
melsalcedo Feb 20, 2026
dfadc7e
refactor(alerts): share scheduleStartAt schema and parser
melsalcedo Feb 20, 2026
b903e61
chore(alerts): clarify anchor start label in forms
melsalcedo Feb 20, 2026
d1a028d
fix(alerts): handle null scheduleStartAt and add scheduling guards
melsalcedo Feb 20, 2026
29af34b
chore(alerts): address review feedback for schedule start
melsalcedo Feb 20, 2026
30c4865
chore(alerts): normalize schedule defaults and 1m offset UX
melsalcedo Feb 20, 2026
32a7267
refactor(alerts): centralize schedule fields and harden API validation
melsalcedo Feb 20, 2026
539b531
fix(alerts): avoid no-op schedule writes for existing alerts
melsalcedo Feb 20, 2026
41e0c26
refactor(alerts): share no-op schedule normalization helper
melsalcedo Feb 20, 2026
6e31044
fix(alerts): tighten scheduleStartAt validation and defaults
melsalcedo Feb 20, 2026
d1498fc
fix(alerts): guard new-alert schedule normalization
melsalcedo Feb 20, 2026
fe52938
chore(alerts): tighten copy and offset bounds
melsalcedo Feb 20, 2026
f7cceef
chore(alerts): clarify offset behavior with anchored start
melsalcedo Feb 20, 2026
6a4c407
chore(alerts): guard anchor bounds and document zod coupling
melsalcedo Feb 20, 2026
be098f9
feat(alerts): enforce anchored offset semantics across layers
melsalcedo Feb 20, 2026
7d502a2
fix(alerts): clear stale offset when scheduleStartAt is set
melsalcedo Feb 20, 2026
e718023
fix(alerts): preserve schema compatibility and harden no-op normaliza…
melsalcedo Feb 20, 2026
6c96d66
fix(common-utils): keep validated alert schemas internal
melsalcedo Feb 20, 2026
2d29bb5
fix(alerts): tighten external validation and clear stale offsets
melsalcedo Feb 20, 2026
3780acd
Merge remote-tracking branch 'upstream/main' into codex/issue-1715-st…
melsalcedo Feb 20, 2026
64052ab
fix(app): preserve explicit alert schedule resets
melsalcedo Feb 28, 2026
da9293d
Merge remote-tracking branch 'upstream/main' into codex/issue-1715-st…
melsalcedo Feb 28, 2026
2f3c582
test(api): cover omitted alert schedule updates
melsalcedo Feb 28, 2026
12d483d
feat(app): collapse alert schedule fields under Advanced Options
teeohhem Mar 2, 2026
2505234
Merge remote-tracking branch 'upstream/main' into codex/issue-1715-st…
melsalcedo Mar 3, 2026
4d199db
feat(app): tuck alert scheduling under advanced settings
melsalcedo Mar 3, 2026
a9c3a0a
Merge remote-tracking branch 'mlsalcedo/startTime-offset' into codex/…
melsalcedo Mar 3, 2026
436adb8
refactor(app): align alert schedule layouts
melsalcedo Mar 3, 2026
3acb031
refactor(api): parse alert requests in middleware
melsalcedo Mar 3, 2026
b4928d7
Merge remote-tracking branch 'upstream/main' into codex/issue-1715-st…
melsalcedo Mar 3, 2026
d1c329a
Merge remote-tracking branch 'upstream/main' into codex/issue-1715-st…
melsalcedo Mar 4, 2026
04efb18
Merge branch 'main' into startTime-offset
mlsalcedo Mar 4, 2026
b1faed3
Merge remote-tracking branch 'upstream/main' into codex/issue-1715-st…
melsalcedo Mar 5, 2026
d302304
Merge branch 'startTime-offset' of https://github.com/mlsalcedo/hyper…
melsalcedo Mar 5, 2026
05b8f25
fix: linitng
teeohhem Mar 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix(app): preserve explicit alert schedule resets
  • Loading branch information
melsalcedo committed Feb 28, 2026
commit 64052ab3bfe8f630c2d25e24ec8f0c97ff26e671
16 changes: 14 additions & 2 deletions packages/app/src/DBSearchPageAlertModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,12 @@ const AlertForm = ({
}) => {
const { data: source } = useSource({ id: sourceId });

const { control, handleSubmit, setValue } = useForm<Alert>({
const {
control,
handleSubmit,
setValue,
formState: { dirtyFields },
} = useForm<Alert>({
defaultValues: defaultValues
? {
...defaultValues,
Expand Down Expand Up @@ -137,7 +142,14 @@ const AlertForm = ({
return (
<form
onSubmit={handleSubmit(data =>
onSubmit(normalizeNoOpAlertScheduleFields(data, defaultValues)),
onSubmit(
normalizeNoOpAlertScheduleFields(data, defaultValues, {
preserveExplicitScheduleOffsetMinutes:
dirtyFields.scheduleOffsetMinutes === true,
preserveExplicitScheduleStartAt:
dirtyFields.scheduleStartAt === true,
}),
),
)}
>
<Stack gap="xs">
Expand Down
36 changes: 30 additions & 6 deletions packages/app/src/components/DBEditTimeChartForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ import {
} from '@/hooks/useFetchMetricResourceAttrs';
import SearchInputV2 from '@/SearchInputV2';
import { getFirstTimestampValueExpression, useSource } from '@/source';
import { AlertWithCreatedBy } from '@/types';
import {
getMetricTableName,
optionsToSelectData,
Expand Down Expand Up @@ -564,6 +565,9 @@ export type SavedChartConfigWithSelectArray = Omit<
};

type SavedChartConfigWithSeries = SavedChartConfig & {
alert?: SavedChartConfig['alert'] & {
createdBy?: AlertWithCreatedBy['createdBy'];
};
series: SavedChartConfigWithSelectArray['select'];
};

Expand Down Expand Up @@ -622,7 +626,7 @@ export default function EditTimeChartForm({
register,
setError,
clearErrors,
formState: { errors, isDirty },
formState: { errors, isDirty, dirtyFields },
} = useForm<SavedChartConfigWithSeries>({
defaultValues: configWithSeries,
values: configWithSeries,
Expand Down Expand Up @@ -782,6 +786,12 @@ export default function EditTimeChartForm({
alert: normalizeNoOpAlertScheduleFields(
config.alert,
chartConfig.alert,
{
preserveExplicitScheduleOffsetMinutes:
dirtyFields.alert?.scheduleOffsetMinutes === true,
preserveExplicitScheduleStartAt:
dirtyFields.alert?.scheduleStartAt === true,
},
),
};

Expand Down Expand Up @@ -813,6 +823,8 @@ export default function EditTimeChartForm({
})();
}, [
chartConfig.alert,
dirtyFields.alert?.scheduleOffsetMinutes,
dirtyFields.alert?.scheduleStartAt,
handleSubmit,
setChartConfig,
setQueriedConfigAndSource,
Expand Down Expand Up @@ -867,6 +879,12 @@ export default function EditTimeChartForm({
alert: normalizeNoOpAlertScheduleFields(
withoutSeries.alert,
chartConfig.alert,
{
preserveExplicitScheduleOffsetMinutes:
dirtyFields.alert?.scheduleOffsetMinutes === true,
preserveExplicitScheduleStartAt:
dirtyFields.alert?.scheduleStartAt === true,
},
),
};
const normalizedChartConfig = normalizeChartConfig(
Expand All @@ -878,7 +896,15 @@ export default function EditTimeChartForm({
onSave?.(normalizedChartConfig);
}
},
[onSave, displayType, tableSource, setError, chartConfig.alert],
[
onSave,
displayType,
tableSource,
setError,
chartConfig.alert,
dirtyFields.alert?.scheduleOffsetMinutes,
dirtyFields.alert?.scheduleStartAt,
],
);

// Track previous values for detecting changes
Expand Down Expand Up @@ -1378,11 +1404,9 @@ export default function EditTimeChartForm({
control={control}
/>
</Group>
{(alert as any)?.createdBy && (
{alert?.createdBy && (
<Text size="xs" opacity={0.6}>
Created by{' '}
{(alert as any).createdBy?.name ||
(alert as any).createdBy?.email}
Created by {alert.createdBy.name || alert.createdBy.email}
</Text>
)}
</Group>
Expand Down
32 changes: 32 additions & 0 deletions packages/app/src/utils/__tests__/alerts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,36 @@ describe('normalizeNoOpAlertScheduleFields', () => {
scheduleStartAt: '2024-01-01T00:00:00.000Z',
});
});

it('keeps an explicit offset reset when requested', () => {
const normalized = normalizeNoOpAlertScheduleFields(
{
scheduleOffsetMinutes: 0,
},
undefined,
{
preserveExplicitScheduleOffsetMinutes: true,
},
);

expect(normalized).toEqual({
scheduleOffsetMinutes: 0,
});
});

it('keeps an explicit start-at clear when requested', () => {
const normalized = normalizeNoOpAlertScheduleFields(
{
scheduleStartAt: null,
},
undefined,
{
preserveExplicitScheduleStartAt: true,
},
);

expect(normalized).toEqual({
scheduleStartAt: null,
});
});
});
20 changes: 17 additions & 3 deletions packages/app/src/utils/alerts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,22 @@ type AlertScheduleFields = {
scheduleStartAt?: string | null;
};

type NormalizeAlertScheduleOptions = {
preserveExplicitScheduleOffsetMinutes?: boolean;
preserveExplicitScheduleStartAt?: boolean;
};

/**
* Keep alert documents backward-compatible by avoiding no-op writes for
* scheduling fields on pre-migration alerts that never had these keys.
*/
export function normalizeNoOpAlertScheduleFields<
T extends AlertScheduleFields | undefined,
>(alert: T, previousAlert?: AlertScheduleFields | null): T {
>(
alert: T,
previousAlert?: AlertScheduleFields | null,
options: NormalizeAlertScheduleOptions = {},
): T {
if (alert == null) {
return alert;
}
Expand All @@ -173,12 +182,17 @@ export function normalizeNoOpAlertScheduleFields<

if (
(normalizedAlert.scheduleOffsetMinutes ?? 0) === 0 &&
!previousHadOffset
!previousHadOffset &&
!options.preserveExplicitScheduleOffsetMinutes
) {
delete normalizedAlert.scheduleOffsetMinutes;
}

if (normalizedAlert.scheduleStartAt == null && !previousHadStartAt) {
if (
normalizedAlert.scheduleStartAt == null &&
!previousHadStartAt &&
!options.preserveExplicitScheduleStartAt
) {
delete normalizedAlert.scheduleStartAt;
}

Expand Down