mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
feat(frontend): add timezone to new library agent page (#10874)
## Changes 🏗️ <img width="800" height="756" alt="Screenshot 2025-09-09 at 14 03 24" src="https://github.com/user-attachments/assets/65f3e3a8-1ce0-491c-824a-601a494d3a36" /> <img width="600" height="493" alt="Screenshot 2025-09-09 at 14 03 28" src="https://github.com/user-attachments/assets/457b37a3-6b3b-49b8-912c-c72cf06e8e58" /> Following the nice changes @ntindle did regarding timezones, bring them into the new page: - display the timezone when scheduling an agent on the new modal - display the timezone for a schedule on the new schedule details view ## Checklist 📋 ### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: - [x] Run the app locally with `agent-new-runs` flag ON - [x] Open an agent on the new page - [x] On the new modal, create a schedule, it display the timezone alert - [x] Once created, on the schedule view, it displays the timezone ### For configuration changes: None
This commit is contained in:
@@ -5,6 +5,7 @@ import { Select } from "@/components/atoms/Select/Select";
|
||||
import { useScheduleView } from "./useScheduleView";
|
||||
import { useCallback, useState } from "react";
|
||||
import { validateSchedule } from "./helpers";
|
||||
import { TimezoneNotice } from "../TimezoneNotice/TimezoneNotice";
|
||||
|
||||
interface Props {
|
||||
scheduleName: string;
|
||||
@@ -141,8 +142,9 @@ export function ScheduleView({
|
||||
placeholder="00:00"
|
||||
error={errors.time}
|
||||
/>
|
||||
|
||||
{/** Agent inputs are rendered in the main modal; none here. */}
|
||||
<div className="-mt-4">
|
||||
<TimezoneNotice />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { useGetV1GetUserTimezone } from "@/app/api/__generated__/endpoints/auth/auth";
|
||||
import { getTimezoneDisplayName } from "@/lib/timezone-utils";
|
||||
import { InfoIcon } from "@phosphor-icons/react";
|
||||
|
||||
export function TimezoneNotice() {
|
||||
const { data: userTimezone, isSuccess } = useGetV1GetUserTimezone({
|
||||
query: {
|
||||
select: (res) => (res.status === 200 ? res.data.timezone : undefined),
|
||||
},
|
||||
});
|
||||
|
||||
if (!isSuccess) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (userTimezone === "not-set") {
|
||||
return (
|
||||
<div className="mt-1 flex items-center gap-2 rounded-md border border-amber-200 bg-amber-50 p-3">
|
||||
<InfoIcon className="h-4 w-4 text-amber-600" />
|
||||
<p className="text-sm text-amber-800">
|
||||
No timezone set. Schedule will run in UTC.
|
||||
<a href="/profile/settings" className="ml-1 underline">
|
||||
Set your timezone
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const tzName = getTimezoneDisplayName(userTimezone || "UTC");
|
||||
|
||||
return (
|
||||
<div className="mt-1 flex items-center gap-2 rounded-md bg-muted/50 p-3">
|
||||
<InfoIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Schedule will run in your timezone:{" "}
|
||||
<span className="font-medium">{tzName}</span>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -25,7 +25,7 @@ import { useScheduleDetailHeader } from "../RunDetailHeader/useScheduleDetailHea
|
||||
import { DeleteScheduleButton } from "./components/DeleteScheduleButton/DeleteScheduleButton";
|
||||
import { humanizeCronExpression } from "@/lib/cron-expression-utils";
|
||||
import { useGetV1GetUserTimezone } from "@/app/api/__generated__/endpoints/auth/auth";
|
||||
import { formatInTimezone } from "@/lib/timezone-utils";
|
||||
import { formatInTimezone, getTimezoneDisplayName } from "@/lib/timezone-utils";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { AgentInputsReadOnly } from "../AgentInputsReadOnly/AgentInputsReadOnly";
|
||||
import { Button } from "@/components/atoms/Button/Button";
|
||||
@@ -96,10 +96,11 @@ export function ScheduleDetails({
|
||||
<RunDetailHeader
|
||||
agent={agent}
|
||||
run={undefined}
|
||||
scheduleRecurrence={humanizeCronExpression(
|
||||
schedule?.cron || "",
|
||||
userTzRes,
|
||||
)}
|
||||
scheduleRecurrence={
|
||||
schedule
|
||||
? `${humanizeCronExpression(schedule.cron || "", userTzRes)} · ${getTimezoneDisplayName(userTzRes || "UTC")}`
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
{schedule ? (
|
||||
@@ -161,6 +162,10 @@ export function ScheduleDetails({
|
||||
</Text>
|
||||
<p className="text-sm text-zinc-600">
|
||||
{humanizeCronExpression(schedule.cron, userTzRes)}
|
||||
{" • "}
|
||||
<span className="text-xs text-zinc-600">
|
||||
{getTimezoneDisplayName(userTzRes || "UTC")}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1.5">
|
||||
@@ -179,7 +184,11 @@ export function ScheduleDetails({
|
||||
minute: "2-digit",
|
||||
hour12: false,
|
||||
},
|
||||
)}
|
||||
)}{" "}
|
||||
•{" "}
|
||||
<span className="text-xs text-zinc-600">
|
||||
{getTimezoneDisplayName(userTzRes || "UTC")}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,6 @@ export function formatInTimezone(
|
||||
day: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
timeZoneName: "short",
|
||||
...options,
|
||||
};
|
||||
|
||||
@@ -112,3 +111,23 @@ export function getTimezoneDisplayName(timezone: string): string {
|
||||
return timezone;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the GMT offset for a given timezone, e.g. "GMT+9" or "UTC"
|
||||
*/
|
||||
export function getTimezoneGmtOffset(timezone: string): string {
|
||||
if (timezone === "not-set" || !timezone) return "";
|
||||
try {
|
||||
const date = new Date();
|
||||
const formatted = new Intl.DateTimeFormat("en-US", {
|
||||
timeZone: timezone,
|
||||
timeZoneName: "short",
|
||||
}).format(date);
|
||||
|
||||
// Common outputs look like "1/1/2024, GMT+9" or "1/1/2024, UTC"
|
||||
const match = formatted.match(/(GMT[+\-]\d{1,2}|UTC)/i);
|
||||
return match ? match[0].toUpperCase() : "";
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user