mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix: fix for template dormancy hour/day toggle (#19884)
resolves #15451 > Solution: Selecting days is always be enabled and rounds (up) the hours to the nearest day. I.e. 25 hours -> 2 days. tested with 26hrs saved, then toggled to days. result = value changed to 2 days If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting. blink helped --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -64,16 +64,27 @@ export const ChangeUnit: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const CantConvertToDays: Story = {
|
||||
export const ConvertSmallHoursToDays: Story = {
|
||||
args: {
|
||||
valueMs: hoursToMs(2),
|
||||
valueMs: hoursToMs(2), // 2 hours should convert to 1 day when switching units (rounded up)
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
// Initially should show 2 hours
|
||||
const input = canvas.getByLabelText("Duration");
|
||||
await expect(input).toHaveValue("2");
|
||||
|
||||
// Switch to days by clicking the dropdown
|
||||
const unitDropdown = canvas.getByLabelText("Time unit");
|
||||
await userEvent.click(unitDropdown);
|
||||
|
||||
// Find and click the Days option - this should now work (no longer disabled)
|
||||
const daysOption = within(document.body).getByText("Days");
|
||||
await expect(daysOption).toHaveAttribute("aria-disabled", "true");
|
||||
await userEvent.click(daysOption);
|
||||
|
||||
// After switching to days, should show 1 day (2 hours rounded up to nearest day)
|
||||
await expect(input).toHaveValue("1");
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -45,19 +45,12 @@ const reducer = (state: State, action: Action): State => {
|
||||
state.unit,
|
||||
);
|
||||
|
||||
if (
|
||||
action.unit === "days" &&
|
||||
!canConvertDurationToDays(currentDurationMs)
|
||||
) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return {
|
||||
unit: action.unit,
|
||||
durationFieldValue:
|
||||
action.unit === "hours"
|
||||
? durationInHours(currentDurationMs).toString()
|
||||
: durationInDays(currentDurationMs).toString(),
|
||||
: Math.ceil(durationInDays(currentDurationMs)).toString(),
|
||||
};
|
||||
}
|
||||
default: {
|
||||
@@ -124,17 +117,30 @@ export const DurationField: FC<DurationFieldProps> = (props) => {
|
||||
type: "CHANGE_TIME_UNIT",
|
||||
unit,
|
||||
});
|
||||
|
||||
// Calculate the new duration in ms after changing the unit
|
||||
// Important: When changing from hours to days, we need to round up to nearest day
|
||||
// but keep the millisecond value consistent for the parent component
|
||||
let newDurationMs: number;
|
||||
if (unit === "hours") {
|
||||
// When switching to hours, use the current milliseconds to get exact hours
|
||||
newDurationMs = currentDurationMs;
|
||||
} else {
|
||||
// When switching to days, round up to the nearest day
|
||||
const daysValue = Math.ceil(durationInDays(currentDurationMs));
|
||||
newDurationMs = daysToDuration(daysValue);
|
||||
}
|
||||
|
||||
// Notify parent component if the value has changed
|
||||
if (newDurationMs !== parentValueMs) {
|
||||
onChange(newDurationMs);
|
||||
}
|
||||
}}
|
||||
inputProps={{ "aria-label": "Time unit" }}
|
||||
IconComponent={ChevronDownIcon}
|
||||
>
|
||||
<MenuItem value="hours">Hours</MenuItem>
|
||||
<MenuItem
|
||||
value="days"
|
||||
disabled={!canConvertDurationToDays(currentDurationMs)}
|
||||
>
|
||||
Days
|
||||
</MenuItem>
|
||||
<MenuItem value="days">Days</MenuItem>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@@ -181,7 +187,3 @@ function hoursToDuration(hours: number): number {
|
||||
function daysToDuration(days: number): number {
|
||||
return days * 24 * hoursToDuration(1);
|
||||
}
|
||||
|
||||
function canConvertDurationToDays(duration: number): boolean {
|
||||
return Number.isInteger(durationInDays(duration));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user