github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/ui/dashboard/src/components/dashboards/layout/Panel/index.tsx (about) 1 import PanelStatus from "./PanelStatus"; 2 import PanelControls from "./PanelControls"; 3 import PanelInformation from "./PanelInformation"; 4 import PanelProgress from "./PanelProgress"; 5 import PanelTitle from "../../titles/PanelTitle"; 6 import Placeholder from "../../Placeholder"; 7 import { BaseChartProps } from "../../charts/types"; 8 import { CardProps } from "../../Card"; 9 import { classNames } from "../../../../utils/styles"; 10 import { DashboardPanelType, PanelDefinition } from "../../../../types"; 11 import { FlowProps } from "../../flows/types"; 12 import { getResponsivePanelWidthClass } from "../../../../utils/layout"; 13 import { GraphProps } from "../../graphs/types"; 14 import { HierarchyProps } from "../../hierarchies/types"; 15 import { ImageProps } from "../../Image"; 16 import { InputProps } from "../../inputs/types"; 17 import { memo, useState } from "react"; 18 import { PanelProvider, usePanel } from "../../../../hooks/usePanel"; 19 import { ReactNode } from "react"; 20 import { registerComponent } from "../../index"; 21 import { TableProps } from "../../Table"; 22 import { TextProps } from "../../Text"; 23 import { useDashboard } from "../../../../hooks/useDashboard"; 24 25 type PanelProps = { 26 children: ReactNode; 27 className?: string; 28 definition: 29 | BaseChartProps 30 | CardProps 31 | FlowProps 32 | GraphProps 33 | HierarchyProps 34 | ImageProps 35 | InputProps 36 | PanelDefinition 37 | TableProps 38 | TextProps; 39 parentType: DashboardPanelType; 40 showControls?: boolean; 41 showPanelError?: boolean; 42 showPanelStatus?: boolean; 43 forceBackground?: boolean; 44 }; 45 46 const Panel = ({ 47 children, 48 className, 49 definition, 50 showControls = true, 51 showPanelError = true, 52 showPanelStatus = true, 53 forceBackground = false, 54 }: PanelProps) => { 55 const { selectedPanel } = useDashboard(); 56 const { 57 inputPanelsAwaitingValue, 58 panelControls, 59 showPanelControls, 60 setShowPanelControls, 61 } = usePanel(); 62 const [referenceElement, setReferenceElement] = useState(null); 63 const baseStyles = classNames( 64 "relative col-span-12", 65 getResponsivePanelWidthClass(definition.width), 66 "overflow-auto" 67 ); 68 69 if (inputPanelsAwaitingValue.length > 0) { 70 return null; 71 } 72 73 const PlaceholderComponent = Placeholder.component; 74 75 const shouldShowLoader = 76 showPanelStatus && 77 definition.status !== "cancelled" && 78 definition.status !== "error" && 79 definition.status !== "complete"; 80 81 const showPanelContents = 82 !definition.error || (definition.error && !showPanelError); 83 84 return ( 85 <div 86 // @ts-ignore 87 ref={setReferenceElement} 88 id={definition.name} 89 className={baseStyles} 90 onMouseEnter={showControls ? () => setShowPanelControls(true) : undefined} 91 onMouseLeave={() => setShowPanelControls(false)} 92 > 93 <section 94 aria-labelledby={ 95 definition.title ? `${definition.name}-title` : undefined 96 } 97 className={classNames( 98 "col-span-12 m-0.5", 99 forceBackground || 100 (definition.panel_type !== "image" && 101 definition.panel_type !== "card" && 102 definition.panel_type !== "input") || 103 ((definition.panel_type === "image" || 104 definition.panel_type === "card" || 105 definition.panel_type === "input") && 106 definition.display_type === "table") 107 ? "bg-dashboard-panel print:bg-white shadow-sm rounded-md" 108 : null 109 )} 110 > 111 {showPanelControls && ( 112 <PanelControls 113 referenceElement={referenceElement} 114 controls={panelControls} 115 /> 116 )} 117 {definition.title && ( 118 <div 119 className={classNames( 120 definition.panel_type === "input" && 121 definition.display_type !== "table" && 122 !forceBackground 123 ? "pl-0 pr-2 sm:pr-4 py-2" 124 : "px-4 py-4" 125 )} 126 > 127 <PanelTitle name={definition.name} title={definition.title} /> 128 </div> 129 )} 130 131 <div 132 className={classNames( 133 "relative", 134 definition.title && 135 ((definition.panel_type !== "input" && 136 // @ts-ignore 137 definition.status !== "complete") || 138 (definition.panel_type !== "input" && 139 definition.panel_type !== "table") || 140 (definition.panel_type === "table" && 141 definition.display_type === "line")) 142 ? "border-t border-divide" 143 : null, 144 selectedPanel || 145 (definition.panel_type === "table" && 146 definition.display_type !== "line") || 147 definition.display_type === "table" 148 ? "overflow-x-auto" 149 : "overflow-x-hidden", 150 className 151 )} 152 > 153 <PanelProgress className={definition.title ? null : "rounded-t-md"} /> 154 <PanelInformation /> 155 <PlaceholderComponent 156 animate={definition.status === "running"} 157 ready={!shouldShowLoader} 158 > 159 <> 160 {((showPanelError && definition.status === "error") || 161 showPanelStatus) && ( 162 <PanelStatus 163 definition={definition as PanelDefinition} 164 showPanelError={showPanelError} 165 /> 166 )} 167 {showPanelContents && children} 168 </> 169 </PlaceholderComponent> 170 </div> 171 </section> 172 </div> 173 ); 174 }; 175 176 const PanelWrapper = memo((props: PanelProps) => { 177 const { children, ...rest } = props; 178 return ( 179 <PanelProvider 180 definition={props.definition} 181 parentType={props.parentType} 182 showControls={props.showControls} 183 > 184 <Panel {...rest}>{children}</Panel> 185 </PanelProvider> 186 ); 187 }); 188 189 registerComponent("panel", PanelWrapper); 190 191 export default PanelWrapper;