diff --git a/app/(dashboard)/browser/page.tsx b/app/(dashboard)/browser/page.tsx index cd1a52cb..98854699 100644 --- a/app/(dashboard)/browser/page.tsx +++ b/app/(dashboard)/browser/page.tsx @@ -20,6 +20,7 @@ import { usePermissions } from "@/hooks/use-permissions" import { useDialog } from "@/lib/feedback/dialog" import { useMessage } from "@/lib/feedback/message" import { niceBytes } from "@/lib/functions" +import { normalizeDateToIso } from "@/lib/safe-date" import { BrowserContent } from "./content" import type { ColumnDef } from "@tanstack/react-table" import dayjs from "dayjs" @@ -154,7 +155,7 @@ function BrowserBucketsPage() { const bucketRow: BucketRow = { Name: name, - CreationDate: item?.CreationDate ? new Date(item.CreationDate).toISOString() : "", + CreationDate: normalizeDateToIso(item?.CreationDate), } return bucketRow diff --git a/components/buckets/list.tsx b/components/buckets/list.tsx index 4cf2b878..51e1ff20 100644 --- a/components/buckets/list.tsx +++ b/components/buckets/list.tsx @@ -12,6 +12,7 @@ import { useBucket } from "@/hooks/use-bucket" import { useSystem } from "@/hooks/use-system" import { Spinner } from "@/components/ui/spinner" import { niceBytes } from "@/lib/functions" +import { normalizeDateToIso } from "@/lib/safe-date" import type { ColumnDef } from "@tanstack/react-table" import dayjs from "dayjs" @@ -132,7 +133,7 @@ export function BucketList({ title, emptyDescription, getBucketHref }: BucketLis return { Name: name, - CreationDate: item?.CreationDate ? new Date(item.CreationDate).toISOString() : "", + CreationDate: normalizeDateToIso(item?.CreationDate), } }) .filter((bucket): bucket is BucketListRow => bucket !== null) diff --git a/components/events/new-form.tsx b/components/events/new-form.tsx index 222f1915..b17971ff 100644 --- a/components/events/new-form.tsx +++ b/components/events/new-form.tsx @@ -13,6 +13,7 @@ import { ScrollArea } from "@/components/ui/scroll-area" import { useBucket } from "@/hooks/use-bucket" import { useEventTarget } from "@/hooks/use-event-target" import { useMessage } from "@/lib/feedback/message" +import { scheduleMicrotask } from "@/lib/schedule-microtask" interface EventsNewFormProps { open: boolean @@ -67,7 +68,7 @@ export function EventsNewForm({ open, onOpenChange, bucketName, onSuccess, disab }, [getEventTargetArnList]) useEffect(() => { - queueMicrotask(() => loadArnList()) + scheduleMicrotask(() => loadArnList()) }, [loadArnList]) const resetForm = useCallback(() => { @@ -81,7 +82,7 @@ export function EventsNewForm({ open, onOpenChange, bucketName, onSuccess, disab useEffect(() => { if (open) { - queueMicrotask(() => resetForm()) + scheduleMicrotask(() => resetForm()) } }, [open, resetForm]) diff --git a/components/object/info.tsx b/components/object/info.tsx index e8e18d00..03b08579 100644 --- a/components/object/info.tsx +++ b/components/object/info.tsx @@ -22,6 +22,7 @@ import { useMessage } from "@/lib/feedback/message" import { useDialog } from "@/lib/feedback/dialog" import { exportFile } from "@/lib/export-file" import { getContentType } from "@/lib/mime-types" +import { normalizeDateToIso } from "@/lib/safe-date" import { getDefaultObjectRetentionDate, getMinimumObjectRetentionDate, @@ -431,7 +432,7 @@ export function ObjectInfo({ bucketName, objectKey, open, onOpenChange, onPrevie } } - const lastModified = object?.LastModified ? new Date(object.LastModified as string | Date).toISOString() : "" + const lastModified = normalizeDateToIso((object?.LastModified as string | Date | undefined) ?? undefined) return ( <> diff --git a/components/object/list.tsx b/components/object/list.tsx index 9e344be9..704dc42f 100644 --- a/components/object/list.tsx +++ b/components/object/list.tsx @@ -40,6 +40,7 @@ import { useMessage } from "@/lib/feedback/message" import { exportFile } from "@/lib/export-file" import { getContentType } from "@/lib/mime-types" import { formatBytes } from "@/lib/functions" +import { normalizeDateToIso } from "@/lib/safe-date" import { buildBucketPath } from "@/lib/bucket-path" import { createObjectListScope, @@ -189,10 +190,24 @@ export function ObjectList({ Key: item.Key ?? "", type: "object" as const, Size: item.Size ?? 0, - LastModified: item.LastModified ? item.LastModified.toISOString() : "", + LastModified: normalizeDateToIso(item.LastModified), })) setData([...prefixItems, ...objectItems]) + } catch (error) { + console.error("Failed to fetch objects:", error) + message.error((error as Error)?.message ?? t("Failed to load objects")) + if ( + shouldApplyObjectListResponse({ + requestId, + activeRequestId: requestIdRef.current, + requestScope, + activeScope: activeScopeRef.current, + }) + ) { + setNextToken(undefined) + setData([]) + } } finally { window.setTimeout(() => { if ( @@ -208,7 +223,7 @@ export function ObjectList({ }, 200) } }, - [bucket, prefix, resolvedPageSize, continuationToken, showDeleted, listObject], + [bucket, prefix, resolvedPageSize, continuationToken, showDeleted, listObject, message, t], ) const prevRefreshTriggerRef = React.useRef(refreshTrigger) diff --git a/components/object/view.tsx b/components/object/view.tsx index 716d9407..8f2e4cb6 100644 --- a/components/object/view.tsx +++ b/components/object/view.tsx @@ -9,6 +9,7 @@ import { useObject } from "@/hooks/use-object" import { useMessage } from "@/lib/feedback/message" import { exportFile } from "@/lib/export-file" import { getContentType } from "@/lib/mime-types" +import { normalizeDateToIso } from "@/lib/safe-date" interface ObjectViewProps { bucketName: string @@ -49,7 +50,7 @@ export function ObjectView({ bucketName, objectKey }: ObjectViewProps) { } } - const lastModified = object?.LastModified ? new Date(object.LastModified as string).toISOString() : "" + const lastModified = normalizeDateToIso((object?.LastModified as string | Date | undefined) ?? undefined) return (