Skip to content

Commit 781431a

Browse files
authored
attributes badge (#389)
* badge * attach attr to cbar name * better open and close
1 parent 86febd5 commit 781431a

File tree

8 files changed

+135
-58
lines changed

8 files changed

+135
-58
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"@radix-ui/react-scroll-area": "^1.2.9",
5050
"@radix-ui/react-separator": "^1.1.7",
5151
"@radix-ui/react-slider": "^1.3.6",
52+
"@radix-ui/react-slot": "^1.2.3",
5253
"@radix-ui/react-tooltip": "^1.2.8",
5354
"@react-spring/three": "^10.0.0",
5455
"@react-three/drei": "^10.0.7",

src/components/LandingHome.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,18 @@ import { ZarrDataset, GetStore } from '@/components/zarr/ZarrLoaderLRU';
66
import { useEffect, useMemo } from 'react';
77
import { PlotArea, Plot, LandingShapes } from '@/components/plots';
88
import { MainPanel } from '@/components/ui';
9-
import { Metadata, Loading, Navbar, Error } from '@/components/ui';
9+
import { Loading, Navbar, Error } from '@/components/ui';
1010
import { useGlobalStore, useZarrStore } from '@/utils/GlobalStates';
1111
import { useShallow } from 'zustand/shallow';
1212

1313
export function LandingHome() {
1414
const {
15-
initStore, timeSeries, variable, metadata, plotOn,
15+
initStore, timeSeries, variable, plotOn,
1616
setZMeta, setVariables, setPlotOn, setTitleDescription,
1717
} = useGlobalStore(useShallow(state => ({
1818
initStore: state.initStore,
1919
timeSeries: state.timeSeries,
2020
variable: state.variable,
21-
metadata: state.metadata,
2221
plotOn: state.plotOn,
2322
setZMeta: state.setZMeta,
2423
setVariables: state.setVariables,
@@ -76,7 +75,6 @@ export function LandingHome() {
7675

7776
{/* {variable === "Default" && <ScrollableLinksTable />} */}
7877
{variable != "Default" && <Plot ZarrDS={ZarrDS} />}
79-
{metadata && <Metadata data={metadata} /> }
8078
{Object.keys(timeSeries).length >= 1 && <PlotArea />}
8179
</>
8280
);

src/components/plots/Plot.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ const Plot = ({ZarrDS}:{ZarrDS: ZarrDataset}) => {
122122

123123
const [textures, setTextures] = useState<THREE.DataTexture[] | THREE.Data3DTexture[] | null>(null)
124124
const [show, setShow] = useState<boolean>(true) //Prevents rendering of 3D objects until data is fully loaded in
125-
125+
const [stableMetadata, setStableMetadata] = useState<Record<string, any>>({});
126126
//DATA LOADING
127127
useEffect(() => {
128128
if (variable != "Default") {
@@ -168,6 +168,7 @@ const Plot = ({ZarrDS}:{ZarrDS: ZarrDataset}) => {
168168
//Get Metadata
169169
ZarrDS.GetAttributes(variable).then((result)=>{
170170
setMetadata(result);
171+
setStableMetadata(result);
171172
let [dimArrs, dimUnits, dimNames] = ZarrDS.GetDimArrays()
172173
if (is4D){
173174
dimArrs = dimArrs.slice(1);
@@ -232,7 +233,7 @@ const Plot = ({ZarrDS}:{ZarrDS: ZarrDataset}) => {
232233
style={{width:'100vw'}}
233234
>
234235
<AnalysisWG setTexture={setTextures} ZarrDS={ZarrDS}/>
235-
{show && <Colorbar units={metadata?.units} valueScales={valueScales}/>}
236+
{show && <Colorbar units={stableMetadata?.units} metadata={stableMetadata} valueScales={valueScales}/>}
236237
<Nav />
237238
{(isFlat || plotType == "flat") && <AnalysisInfo loc={loc} show={showInfo} info={[...coords.current,val.current]}/> }
238239
{((!isFlat && plotType != "flat") || (isFlat && plotType === 'sphere')) && <>

src/components/ui/Colorbar.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { useGlobalStore, usePlotStore, useAnalysisStore } from '@/utils/GlobalSt
88
import { useShallow } from 'zustand/shallow'
99
import './css/Colorbar.css'
1010
import { linspace, TwoDecimals } from '@/utils/HelperFuncs';
11+
import Metadata from "./MetaData";
1112

1213
const operationMap = {
1314
// Reductions
@@ -37,7 +38,7 @@ const operationMap = {
3738
CUMSUM3D: "Cumulative Sum"
3839
};
3940

40-
const Colorbar = ({units, valueScales} : {units: string, valueScales: {maxVal: number, minVal:number}}) => {
41+
const Colorbar = ({units, metadata, valueScales} : {units: string, metadata: Record<string, any>, valueScales: {maxVal: number, minVal:number}}) => {
4142
const {colormap, variable} = useGlobalStore(useShallow(state => ({
4243
colormap: state.colormap,
4344
variable: state.variable
@@ -227,7 +228,8 @@ const Colorbar = ({units, valueScales} : {units: string, valueScales: {maxVal: n
227228
left:'50%',
228229
transform:'translateX(-50%)',
229230
}}>
230-
{`${variable} ${analysisString}`}
231+
{<Metadata data={metadata} variable ={variable} />}
232+
{`${analysisString}`}
231233
</p>
232234
{(cScale != 1 || cOffset != 0) && <RxReset size={25} style={{position:'absolute', top:'-25px', cursor:'pointer'}}
233235
onClick={()=>{setNewMin(origMin); setNewMax(origMax)}}

src/components/ui/MainPanel/MetaDataInfo.tsx

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useAnalysisStore, useCacheStore, useGlobalStore, usePlotStore, useZarrS
33
import { useShallow } from 'zustand/shallow'
44
import { SliderThumbs } from "@/components/ui/SliderThumbs"
55
import { Button } from "@/components/ui/button"
6+
import Metadata, { defaultAttributes, renderAttributes } from "@/components/ui/MetaData"
67
import { Input } from "../input"
78
import { BsFillQuestionCircleFill } from "react-icons/bs";
89
import { parseLoc } from "@/utils/HelperFuncs"
@@ -11,7 +12,8 @@ import {
1112
TooltipContent,
1213
TooltipTrigger,
1314
} from "@/components/ui/tooltip";
14-
15+
import {Popover, PopoverTrigger, PopoverContent} from "@/components/ui/popover"
16+
import { Badge } from "@/components/ui/badge"
1517

1618
const formatArray = (value: string | number[]): string => {
1719
if (typeof value === 'string') return value
@@ -54,7 +56,7 @@ function HandleCustomSteps(e: string, chunkSize: number){
5456
}
5557

5658

57-
const MetaDataInfo = ({ meta, setShowMeta, setOpenVariables }: { meta: any, setShowMeta: React.Dispatch<React.SetStateAction<boolean>>, setOpenVariables: React.Dispatch<React.SetStateAction<boolean>> }) => {
59+
const MetaDataInfo = ({ meta, metadata, setShowMeta, setOpenVariables, popoverSide }: { meta: any, metadata: Record<string, any>, setShowMeta: React.Dispatch<React.SetStateAction<boolean>>, setOpenVariables: React.Dispatch<React.SetStateAction<boolean>>, popoverSide: string }) => {
5860
const {is4D, idx4D, variable, initStore, setIs4D, setIdx4D, setVariable, setTextureArrayDepths} = useGlobalStore(useShallow(state => ({
5961
is4D: state.is4D,
6062
idx4D: state.idx4D,
@@ -191,9 +193,25 @@ const MetaDataInfo = ({ meta, setShowMeta, setOpenVariables }: { meta: any, setS
191193
// Don't put any more work in the landing page version. Since it won't be visible in the future
192194
// The logic here was to just get divs to be used later in a Card or Dialog component!
193195
<>
194-
<div className="meta-info">
195-
<b>Long Name</b> <br/>
196-
{`${meta.long_name}`}<br/>
196+
<b>{`${meta.long_name} `}</b>
197+
{ popoverSide=="left" ? <Popover>
198+
<PopoverTrigger className="cursor-pointer" asChild>
199+
<Badge variant="default">
200+
Attributes
201+
</Badge>
202+
</PopoverTrigger>
203+
<PopoverContent
204+
data-meta-popover
205+
className="max-h-[50vh] overflow-y-auto max-w-200"
206+
align="center"
207+
>
208+
{renderAttributes(metadata, defaultAttributes)}
209+
</PopoverContent>
210+
</Popover>
211+
:
212+
<Metadata data={metadata} variable ={'Attributes'} />
213+
}
214+
<br/>
197215
<br/>
198216
<div className="grid grid-cols-2">
199217
<div>
@@ -367,7 +385,6 @@ const MetaDataInfo = ({ meta, setShowMeta, setOpenVariables }: { meta: any, setS
367385
</div>
368386
</>}
369387
</>}
370-
</div>
371388
<div className="grid gap-2 mt-2">
372389
{cached &&
373390
<div>

src/components/ui/MainPanel/Variables.tsx

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import React, { useState, useEffect, useMemo } from "react";
44
import { TbVariable } from "react-icons/tb";
5-
import { useGlobalStore } from "@/utils/GlobalStates";
5+
import { useGlobalStore, useZarrStore } from "@/utils/GlobalStates";
66
import { useShallow } from "zustand/shallow";
77
import { Separator } from "@/components/ui/separator";
88
import MetaDataInfo from "./MetaDataInfo";
@@ -20,6 +20,7 @@ import {
2020
DialogContent,
2121
DialogTitle,
2222
} from "@/components/ui/dialog";
23+
import { ZarrDataset } from "@/components/zarr/ZarrLoaderLRU";
2324

2425
const Variables = ({
2526
openVariables,
@@ -32,13 +33,20 @@ const Variables = ({
3233
const [openMetaPopover, setOpenMetaPopover] = useState(false);
3334

3435
const [showMeta, setShowMeta] = useState(false);
35-
const { variables, zMeta, initStore } = useGlobalStore(
36+
const { variables, zMeta, metadata, setMetadata, initStore } = useGlobalStore(
3637
useShallow((state) => ({
3738
variables: state.variables,
3839
zMeta: state.zMeta,
40+
metadata: state.metadata,
41+
setMetadata: state.setMetadata,
3942
initStore: state.initStore
4043
}))
4144
);
45+
const { currentStore } = useZarrStore(useShallow(state => ({
46+
currentStore: state.currentStore,
47+
})))
48+
const ZarrDS = useMemo(() => new ZarrDataset(currentStore), [currentStore])
49+
4250
const [dimArrays, setDimArrays] = useState([[0],[0],[0]])
4351
const [dimUnits, setDimUnits] = useState([null,null,null])
4452
const [dimNames, setDimNames] = useState<string[]> (["Default"])
@@ -61,6 +69,7 @@ const Variables = ({
6169
const relevant = zMeta.find((e: any) => e.name === selectedVar);
6270
if (relevant){
6371
setMeta({...relevant, dimInfo : {dimArrays, dimNames, dimUnits}});
72+
ZarrDS.GetAttributes(selectedVar).then(e=>setMetadata(e))
6473
}
6574
}
6675
}, [selectedVar, variables, zMeta, dimArrays, dimNames, dimUnits]);
@@ -69,6 +78,7 @@ const Variables = ({
6978
setSelectedIndex(null)
7079
setSelectedVar(null)
7180
setMeta(null)
81+
setMetadata(null)
7282
},[initStore])
7383

7484
useEffect(() => {
@@ -191,9 +201,11 @@ const Variables = ({
191201
>
192202
{meta && (
193203
<MetaDataInfo
194-
meta={meta}
204+
meta={meta}
205+
metadata={metadata??{}}
195206
setShowMeta={setOpenMetaPopover}
196207
setOpenVariables={setOpenVariables}
208+
popoverSide={"left"}
197209
/>
198210
)}
199211
</PopoverContent>
@@ -202,12 +214,16 @@ const Variables = ({
202214
{popoverSide === "top" && (
203215
<Dialog open={showMeta} onOpenChange={setShowMeta}>
204216
<DialogContent className="max-w-[85%] md:max-w-2xl max-h-[80vh] overflow-y-auto">
205-
<DialogTitle className="text-center text-lg font-semibold">
206-
{selectedVar}
207-
</DialogTitle>
208-
<div className="mt-4">
217+
<DialogTitle>{}</DialogTitle>
218+
<div className="-mt-4">
209219
{meta && (
210-
<MetaDataInfo meta={meta} setShowMeta={setShowMeta} setOpenVariables={setOpenVariables}/>
220+
<MetaDataInfo
221+
meta={meta}
222+
metadata={metadata??{}}
223+
setShowMeta={setShowMeta}
224+
setOpenVariables={setOpenVariables}
225+
popoverSide={"top"}
226+
/>
211227
)}
212228
</div>
213229
</DialogContent>

src/components/ui/MetaData.tsx

Lines changed: 32 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020

2121
import { Button } from "@/components/ui/button"
2222

23-
const defaultAttributes = [
23+
export const defaultAttributes = [
2424
"long_name",
2525
"description",
2626
"units",
@@ -51,7 +51,7 @@ export function renderAttributes(
5151
>
5252
{key}:
5353
</div>
54-
<div className="font-mono whitespace-pre-wrap break-words md:col-start-2 md:row-start-auto pl-4 md:pl-0"
54+
<div className="font-mono whitespace-pre-wrap break-words md:col-start-2 md:row-start-auto pl-4 md:pl-2"
5555
style={{ overflowWrap: 'anywhere' }}
5656
>
5757
{typeof value === 'object' ? JSON.stringify(value) : String(value)}
@@ -60,41 +60,37 @@ export function renderAttributes(
6060
);
6161
});
6262
}
63-
const Metadata = ({ data }: { data: Record<string, any> }) => {
63+
const Metadata = ({ data, variable }: { data: Record<string, any>, variable: string }) => {
6464
return (
65-
<div className="metadata-container">
66-
<Dialog>
67-
<Tooltip delayDuration={500} >
68-
<TooltipTrigger asChild>
69-
<DialogTrigger asChild>
70-
<div>
71-
<Button
72-
variant="ghost"
73-
size="icon"
74-
className="size-6 cursor-pointer"
75-
tabIndex={0}
76-
>
77-
<HiInformationCircle className="size-6" />
78-
</Button>
79-
</div>
80-
</DialogTrigger>
81-
</TooltipTrigger>
82-
<TooltipContent side="bottom" align="start">
83-
<span>Show Variable Attributes</span>
84-
</TooltipContent>
85-
</Tooltip>
86-
<DialogContent aria-describedby="Metadata Information for variable" className="metadata-dialog">
87-
<DialogHeader>
88-
<DialogTitle>Attributes</DialogTitle>
89-
</DialogHeader>
90-
<div className="max-h-[60vh] text-[12px] overflow-y-auto break-words p-0">
91-
<div className="grid grid-cols-1 md:grid-cols-[max-content_1fr] gap-x-3 gap-y-[6px]">
92-
{renderAttributes(data, defaultAttributes)}
93-
</div>
94-
</div>
95-
</DialogContent>
96-
</Dialog>
97-
</div>
65+
<Dialog>
66+
<Tooltip delayDuration={500} >
67+
<TooltipTrigger asChild>
68+
<DialogTrigger asChild>
69+
<Button
70+
variant={variable == "Attributes" ? "default" : "ghost"}
71+
size="icon"
72+
className="size-6 w-auto cursor-pointer px-2"
73+
tabIndex={0}
74+
>
75+
{variable}
76+
</Button>
77+
</DialogTrigger>
78+
</TooltipTrigger>
79+
<TooltipContent side="bottom" align="start">
80+
<span>Show Variable Attributes</span>
81+
</TooltipContent>
82+
</Tooltip>
83+
<DialogContent aria-describedby="Metadata Information for variable" className="metadata-dialog">
84+
<DialogHeader>
85+
<DialogTitle>Attributes</DialogTitle>
86+
</DialogHeader>
87+
<div className="max-h-[60vh] text-[12px] overflow-y-auto break-words p-0">
88+
<div className="grid grid-cols-1 md:grid-cols-[max-content_1fr] gap-x-1 gap-y-[6px]">
89+
{renderAttributes(data, defaultAttributes)}
90+
</div>
91+
</div>
92+
</DialogContent>
93+
</Dialog>
9894
);
9995
};
10096

src/components/ui/badge.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import * as React from "react"
2+
import { Slot } from "@radix-ui/react-slot"
3+
import { cva, type VariantProps } from "class-variance-authority"
4+
5+
import { cn } from "@/lib/utils"
6+
7+
const badgeVariants = cva(
8+
"inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
9+
{
10+
variants: {
11+
variant: {
12+
default:
13+
"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
14+
secondary:
15+
"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
16+
destructive:
17+
"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
18+
outline:
19+
"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
20+
},
21+
},
22+
defaultVariants: {
23+
variant: "default",
24+
},
25+
}
26+
)
27+
28+
function Badge({
29+
className,
30+
variant,
31+
asChild = false,
32+
...props
33+
}: React.ComponentProps<"span"> &
34+
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
35+
const Comp = asChild ? Slot : "span"
36+
37+
return (
38+
<Comp
39+
data-slot="badge"
40+
className={cn(badgeVariants({ variant }), className)}
41+
{...props}
42+
/>
43+
)
44+
}
45+
46+
export { Badge, badgeVariants }

0 commit comments

Comments
 (0)