mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-05-27 00:14:22 +00:00
enhance: convert to local time on client
This commit is contained in:
parent
eb0cba12c6
commit
d771c29b0a
6 changed files with 72 additions and 38 deletions
|
|
@ -61,6 +61,7 @@
|
|||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.1.1",
|
||||
"csv-parser": "^3.2.0",
|
||||
"date-fns": "^3.6.0",
|
||||
"dompurify": "^3.2.7",
|
||||
"electron-log": "^5.4.0",
|
||||
"electron-updater": "^6.3.9",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
} from "@/components/ui/popover";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import folderIcon from "@/assets/Folder-1.svg";
|
||||
import { formatDateTime } from "@/lib/utils";
|
||||
|
||||
interface TaskItemProps {
|
||||
task: HistoryTask;
|
||||
|
|
@ -72,8 +73,7 @@ export default function TaskItem({
|
|||
|
||||
const formatDate = (dateString?: string) => {
|
||||
if (!dateString) return "";
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleDateString() + " " + date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
return formatDateTime(dateString, "MMM dd, yyyy HH:mm");
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { useEffect, useState } from "react";
|
|||
import { proxyFetchTrigger, proxyFetchTriggerExecutions } from "@/service/triggerApi";
|
||||
import { useActivityLogStore, ActivityType } from "@/store/activityLogStore";
|
||||
import { Trigger, TriggerExecution, ExecutionStatus } from "@/types";
|
||||
import { formatTime, formatRelativeTime } from "@/lib/utils";
|
||||
|
||||
export interface ExecutionLogEntry {
|
||||
id: number;
|
||||
|
|
@ -52,37 +53,6 @@ const formatDuration = (seconds?: number): string | undefined => {
|
|||
return `${minutes}m ${remainingSeconds.toFixed(0)}s`;
|
||||
};
|
||||
|
||||
// Helper function to format relative time
|
||||
const formatRelativeTime = (dateString?: string): string => {
|
||||
if (!dateString) return "Never";
|
||||
|
||||
const date = new Date(dateString);
|
||||
const now = new Date();
|
||||
const diffMs = now.getTime() - date.getTime();
|
||||
const diffMins = Math.floor(diffMs / 60000);
|
||||
const diffHours = Math.floor(diffMs / 3600000);
|
||||
const diffDays = Math.floor(diffMs / 86400000);
|
||||
|
||||
if (diffMins < 1) return "Just now";
|
||||
if (diffMins < 60) return `${diffMins} minute${diffMins > 1 ? 's' : ''} ago`;
|
||||
if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`;
|
||||
if (diffDays === 1) return "Yesterday";
|
||||
if (diffDays < 7) return `${diffDays} days ago`;
|
||||
|
||||
return date.toLocaleDateString();
|
||||
};
|
||||
|
||||
// Helper function to format timestamp
|
||||
const formatTimestamp = (dateString: string): string => {
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleTimeString('en-US', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
hour12: false
|
||||
});
|
||||
};
|
||||
|
||||
// Helper function to transform TriggerExecution to ExecutionLogEntry
|
||||
const transformToLogEntry = (execution: TriggerExecution): ExecutionLogEntry => {
|
||||
const status = mapExecutionStatus(execution.status);
|
||||
|
|
@ -118,7 +88,7 @@ const transformToLogEntry = (execution: TriggerExecution): ExecutionLogEntry =>
|
|||
|
||||
return {
|
||||
id: execution.id,
|
||||
timestamp: formatTimestamp(execution.started_at || execution.created_at || new Date().toISOString()),
|
||||
timestamp: formatTime(execution.started_at || execution.created_at),
|
||||
status,
|
||||
message,
|
||||
duration,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
} from "@/components/ui/dropdown-menu";
|
||||
import { Zap, Clock, MoreHorizontal, Edit, Copy, Trash2, Globe, MessageSquare } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { formatDateTime } from "@/lib/utils";
|
||||
|
||||
type TriggerListItemProps = {
|
||||
trigger: Trigger;
|
||||
|
|
@ -60,8 +61,7 @@ export const TriggerListItem: React.FC<TriggerListItemProps> = ({
|
|||
|
||||
const formatLastExecution = (dateString?: string) => {
|
||||
if (!dateString) return t("triggers.never");
|
||||
const date = new Date(dateString);
|
||||
return `${date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} ${date.toLocaleDateString([], { month: 'short', day: 'numeric' })}`;
|
||||
return formatDateTime(dateString, "HH:mm MMM dd");
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,69 @@
|
|||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
import { formatDistanceToNow, format, parseISO } from "date-fns"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
||||
/**
|
||||
* Date/Time Utilities
|
||||
* All functions expect UTC ISO strings from API and convert to local timezone
|
||||
*/
|
||||
|
||||
/**
|
||||
* Format UTC timestamp to local time (HH:mm:ss)
|
||||
* @param utcString - ISO 8601 UTC timestamp from API
|
||||
*/
|
||||
export function formatTime(utcString: string | null | undefined): string {
|
||||
if (!utcString) return "N/A";
|
||||
try {
|
||||
const date = parseISO(utcString.endsWith('Z') ? utcString : utcString + 'Z');
|
||||
return format(date, "HH:mm:ss");
|
||||
} catch {
|
||||
return "Invalid time";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format UTC timestamp to local date and time
|
||||
* @param utcString - ISO 8601 UTC timestamp from API
|
||||
* @param formatStr - date-fns format string (default: "MMM dd, yyyy HH:mm")
|
||||
*/
|
||||
export function formatDateTime(utcString: string | null | undefined, formatStr: string = "MMM dd, yyyy HH:mm"): string {
|
||||
if (!utcString) return "N/A";
|
||||
try {
|
||||
const date = parseISO(utcString.endsWith('Z') ? utcString : utcString + 'Z');
|
||||
return format(date, formatStr);
|
||||
} catch {
|
||||
return "Invalid date";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format UTC timestamp to local date only
|
||||
* @param utcString - ISO 8601 UTC timestamp from API
|
||||
*/
|
||||
export function formatDate(utcString: string | null | undefined): string {
|
||||
if (!utcString) return "N/A";
|
||||
try {
|
||||
const date = parseISO(utcString.endsWith('Z') ? utcString : utcString + 'Z');
|
||||
return format(date, "MMM dd, yyyy");
|
||||
} catch {
|
||||
return "Invalid date";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format UTC timestamp as relative time (e.g., "2 hours ago")
|
||||
* @param utcString - ISO 8601 UTC timestamp from API
|
||||
*/
|
||||
export function formatRelativeTime(utcString: string | null | undefined): string {
|
||||
if (!utcString) return "N/A";
|
||||
try {
|
||||
const date = parseISO(utcString.endsWith('Z') ? utcString : utcString + 'Z');
|
||||
return formatDistanceToNow(date, { addSuffix: true });
|
||||
} catch {
|
||||
return "Invalid date";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import { useTriggerStore } from "@/store/triggerStore";
|
|||
import { useActivityLogStore, ActivityType } from "@/store/activityLogStore";
|
||||
import { Trigger, TriggerInput, TriggerStatus } from "@/types";
|
||||
import { toast } from "sonner";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import { formatRelativeTime } from "@/lib/utils";
|
||||
import useChatStoreAdapter from "@/hooks/useChatStoreAdapter";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
|
||||
|
|
@ -331,7 +331,7 @@ export default function Overview() {
|
|||
{activityLogs.slice(0, 50).map((log) => {
|
||||
const Icon = getActivityIcon(log.type);
|
||||
const notificationType = getActivityNotificationType(log.type);
|
||||
const timeAgo = formatDistanceToNow(log.timestamp, { addSuffix: true });
|
||||
const timeAgo = formatRelativeTime(log.timestamp.toISOString());
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue