From 9f235582631676b20cc49839dedfb2b9a500f3e5 Mon Sep 17 00:00:00 2001 From: Lazaro Alonso Date: Tue, 13 Jan 2026 09:25:49 +0100 Subject: [PATCH] accept all, validate later --- .../components/loading/LocalNetCDFMeta.tsx | 47 +++++++++---- docs/next-js/components/ui/alert.tsx | 66 +++++++++++++++++++ 2 files changed, 102 insertions(+), 11 deletions(-) create mode 100644 docs/next-js/components/ui/alert.tsx diff --git a/docs/next-js/components/loading/LocalNetCDFMeta.tsx b/docs/next-js/components/loading/LocalNetCDFMeta.tsx index 3c18491..b349387 100644 --- a/docs/next-js/components/loading/LocalNetCDFMeta.tsx +++ b/docs/next-js/components/loading/LocalNetCDFMeta.tsx @@ -3,40 +3,56 @@ import React, { ChangeEvent, useState } from 'react'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; -// import { MetaNetCDFAccordion } from './MetaNetCDFAccordion'; -import { MetaNetCDFButtons } from './MetaNetCDFButtons'; +import { + Alert, + AlertDescription, + AlertTitle, +} from '@/components/ui/alert'; +import { Terminal } from 'lucide-react'; +import { MetaNetCDFButtons } from './MetaNetCDFButtons'; import { NetCDF4 } from '@earthyscience/netcdf4-wasm'; import BrowzarrCTA from './BrowzarrCTA'; + +const NETCDF_EXT_REGEX = /\.(nc|netcdf|nc3|nc4)$/i; + const LocalNetCDFMeta = () => { const [variables, setVariables] = useState | null>(null); const [attributes, setAttributes] = useState | null>(null); const [metadata, setMetadata] = useState[] | null>(null); + const [error, setError] = useState(null); const handleFileSelect = async ( event: ChangeEvent ) => { + setError(null); + const files = event.target.files; if (!files || files.length === 0) return; const file = files[0]; + // Manual validation (iOS-safe) + if (!NETCDF_EXT_REGEX.test(file.name)) { + setError('Please select a valid NetCDF (.nc, .netcdf, .nc3, .nc4) file.'); + return; + } + try { const data = await NetCDF4.fromBlobLazy(file); - const [variables, attrs, metadata] = await Promise.all([ + const [vars, attrs, meta] = await Promise.all([ data.getVariables(), data.getGlobalAttributes(), data.getFullMetadata(), ]); - setVariables(variables); + setVariables(vars); setAttributes(attrs); - setMetadata(metadata); - - } catch (error) { - console.error('Error loading NetCDF file:', error); - alert('Failed to load NetCDF file. Check console for details.'); + setMetadata(meta); + } catch (err) { + console.error('Error loading NetCDF file:', err); + setError('Failed to load NetCDF file. Check console for details.'); } }; @@ -52,11 +68,20 @@ const LocalNetCDFMeta = () => { - + + {error && ( + + + Hey! + + {error} + + + )} + {variables && attributes && metadata && (
svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", + { + variants: { + variant: { + default: "bg-card text-card-foreground", + destructive: + "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +function Alert({ + className, + variant, + ...props +}: React.ComponentProps<"div"> & VariantProps) { + return ( +
+ ) +} + +function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function AlertDescription({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ ) +} + +export { Alert, AlertTitle, AlertDescription }