github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/ui/dashboard/src/components/dashboards/layout/PanelDetail/index.tsx (about) 1 import Grid from "../Grid"; 2 import NeutralButton from "../../../forms/NeutralButton"; 3 import PanelDetailData from "./PanelDetailData"; 4 import PanelDetailDataDownloadButton from "./PanelDetailDataDownloadButton"; 5 import PanelDetailDefinition from "./PanelDetailDefinition"; 6 import PanelDetailLog from "./PanelDetailLog"; 7 import PanelDetailPreview from "./PanelDetailPreview"; 8 import PanelDetailQuery from "./PanelDetailQuery"; 9 import { classNames } from "../../../../utils/styles"; 10 import { DashboardDataModeLive, PanelDefinition } from "../../../../types"; 11 import { useDashboard } from "../../../../hooks/useDashboard"; 12 import { useMemo, useState } from "react"; 13 14 export type PanelDetailProps = { 15 definition: PanelDefinition; 16 }; 17 18 const Tabs = { 19 PREVIEW: { 20 name: "preview", 21 label: "Preview", 22 Component: PanelDetailPreview, 23 }, 24 QUERY: { 25 name: "query", 26 label: "Query", 27 Component: PanelDetailQuery, 28 }, 29 DEFINITION: { 30 name: "definition", 31 label: "Definition", 32 Component: PanelDetailDefinition, 33 }, 34 DATA: { 35 name: "data", 36 label: "Data", 37 Component: PanelDetailData, 38 }, 39 LOG: { 40 name: "log", 41 label: "Log", 42 Component: PanelDetailLog, 43 }, 44 }; 45 46 const PanelDetail = ({ definition }: PanelDetailProps) => { 47 const [selectedTab, setSelectedTab] = useState(Tabs.PREVIEW); 48 const { 49 breakpointContext: { minBreakpoint }, 50 closePanelDetail, 51 dataMode, 52 panelsLog, 53 } = useDashboard(); 54 const isTablet = minBreakpoint("md"); 55 56 const panelLog = panelsLog[definition.name]; 57 58 const availableTabs = useMemo(() => { 59 const tabs = [ 60 { 61 ...Tabs.PREVIEW, 62 selected: selectedTab.name === Tabs.PREVIEW.name, 63 }, 64 ]; 65 if (definition.sql) { 66 tabs.push({ 67 ...Tabs.QUERY, 68 selected: selectedTab.name === Tabs.QUERY.name, 69 }); 70 } 71 if (definition.source_definition) { 72 tabs.push({ 73 ...Tabs.DEFINITION, 74 selected: selectedTab.name === Tabs.DEFINITION.name, 75 }); 76 } 77 if (definition.data) { 78 tabs.push({ 79 ...Tabs.DATA, 80 selected: selectedTab.name === Tabs.DATA.name, 81 }); 82 } 83 if ( 84 dataMode === DashboardDataModeLive && 85 definition.panel_type !== "benchmark" && 86 definition.panel_type !== "control" && 87 !!panelLog 88 ) { 89 tabs.push({ 90 ...Tabs.LOG, 91 selected: selectedTab.name === Tabs.LOG.name, 92 }); 93 } 94 return tabs; 95 }, [dataMode, definition, panelLog, selectedTab]); 96 97 return ( 98 <div className="h-full overflow-y-auto p-4"> 99 <Grid name={definition.name}> 100 <div className="col-span-6"> 101 <h2 className="break-keep">{definition.title || "Panel Detail"}</h2> 102 </div> 103 <div className="col-span-6 space-x-2 text-right"> 104 <PanelDetailDataDownloadButton 105 panelDefinition={definition} 106 size={isTablet ? "md" : "sm"} 107 /> 108 <NeutralButton 109 onClick={closePanelDetail} 110 size={isTablet ? "md" : "sm"} 111 > 112 <> 113 Close<span className="ml-2 font-light text-xxs">ESC</span> 114 </> 115 </NeutralButton> 116 </div> 117 <div className="col-span-12 sm:hidden "> 118 <label htmlFor="tabs" className="sr-only"> 119 Select a tab 120 </label> 121 {/* Use an "onChange" listener to redirect the user to the selected tab URL. */} 122 <select 123 id="tabs" 124 name="tabs" 125 className="mt-2 block w-full pl-3 pr-10 py-2 bg-dashboard print:bg-white text-foreground border-black-scale-3 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm rounded-md" 126 defaultValue={selectedTab.name} 127 onChange={(e) => 128 setSelectedTab( 129 availableTabs.find((tab) => tab.name === e.target.value) || 130 availableTabs[0] 131 ) 132 } 133 > 134 {availableTabs.map((tab) => ( 135 <option key={tab.name} value={tab.name}> 136 {tab.label} 137 </option> 138 ))} 139 </select> 140 </div> 141 <div className="col-span-12 hidden sm:block"> 142 <div className="border-b border-black-scale-3"> 143 <nav className="-mb-px flex space-x-6" aria-label="Tabs"> 144 {availableTabs.map((tab) => ( 145 <span 146 key={tab.name} 147 className={classNames( 148 tab.selected 149 ? "border-black-scale-4 text-foreground cursor-pointer" 150 : "border-transparent text-foreground-lighter hover:text-foreground cursor-pointer", 151 "whitespace-nowrap py-3 px-1 border-b-2 font-medium text-sm" 152 )} 153 onClick={() => setSelectedTab(tab)} 154 > 155 {tab.label} 156 </span> 157 ))} 158 </nav> 159 </div> 160 </div> 161 162 <div className="col-span-12 mt-4"> 163 {<selectedTab.Component definition={definition} />} 164 </div> 165 </Grid> 166 </div> 167 ); 168 }; 169 170 export default PanelDetail;