github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/ui/dashboard/src/components/dashboards/layout/Panel/PanelStatus.tsx (about) 1 import ErrorMessage from "../../../ErrorMessage"; 2 import Icon from "../../../Icon"; 3 import LoadingIndicator from "../../LoadingIndicator"; 4 import usePanelDependenciesStatus from "../../../../hooks/usePanelDependenciesStatus"; 5 import { classNames } from "../../../../utils/styles"; 6 import { HashLink } from "react-router-hash-link"; 7 import { InputProperties } from "../../inputs/types"; 8 import { PanelDefinition } from "../../../../types"; 9 import { ReactNode } from "react"; 10 import { useLocation } from "react-router-dom"; 11 12 type PanelStatusProps = PanelStatusBaseProps & { 13 definition: PanelDefinition; 14 showPanelError: boolean; 15 }; 16 17 type PanelStatusBaseProps = { 18 definition: PanelDefinition; 19 }; 20 21 type BasePanelStatusProps = { 22 children: ReactNode; 23 className?: string; 24 definition: PanelDefinition; 25 }; 26 27 const BasePanelStatus = ({ 28 children, 29 className, 30 definition, 31 }: BasePanelStatusProps) => ( 32 <div 33 className={classNames( 34 className, 35 "w-full h-full p-4 break-keep rounded-md", 36 !!definition.title ? "rounded-t-none" : null 37 )} 38 > 39 {children} 40 </div> 41 ); 42 43 const PanelInitialized = ({ definition }: PanelStatusBaseProps) => { 44 return ( 45 <BasePanelStatus definition={definition}> 46 <div className="flex items-center space-x-1"> 47 <LoadingIndicator className="w-3.5 h-3.5 text-foreground-light shrink-0" /> 48 <span className="block truncate">Initialized...</span> 49 </div> 50 </BasePanelStatus> 51 ); 52 }; 53 54 const PanelBlocked = ({ definition }) => { 55 const panelDependenciesStatus = usePanelDependenciesStatus(); 56 const location = useLocation(); 57 return ( 58 <BasePanelStatus definition={definition}> 59 <div className="flex items-center space-x-1"> 60 {panelDependenciesStatus.inputsAwaitingValue.length > 0 && ( 61 <> 62 <Icon 63 className="w-3.5 h-3.5 text-foreground-light shrink-0" 64 icon="block" 65 /> 66 <span className="block truncate"> 67 Awaiting input:{" "} 68 <HashLink 69 className="text-link" 70 to={`${location.pathname}${ 71 location.search ? location.search : "" 72 }#${panelDependenciesStatus.inputsAwaitingValue[0].name}`} 73 > 74 {panelDependenciesStatus.inputsAwaitingValue[0].title || 75 ( 76 panelDependenciesStatus.inputsAwaitingValue[0] 77 .properties as InputProperties 78 ).unqualified_name} 79 </HashLink> 80 </span> 81 </> 82 )} 83 {panelDependenciesStatus.inputsAwaitingValue.length === 0 && 84 panelDependenciesStatus.total === 0 && ( 85 <> 86 <LoadingIndicator className="w-3.5 h-3.5 text-foreground-light shrink-0" /> 87 <span className="block truncate">Loading...</span> 88 </> 89 )} 90 {panelDependenciesStatus.inputsAwaitingValue.length === 0 && 91 panelDependenciesStatus.total > 0 && ( 92 <> 93 <LoadingIndicator className="w-3.5 h-3.5 text-foreground-light shrink-0" /> 94 <span className="block truncate"> 95 Loading{" "} 96 {panelDependenciesStatus.status.complete.total + 97 panelDependenciesStatus.status.running.total + 98 1}{" "} 99 of {panelDependenciesStatus.total + 1}... 100 </span> 101 </> 102 )} 103 </div> 104 </BasePanelStatus> 105 ); 106 }; 107 108 const PanelRunning = ({ definition }) => { 109 const panelDependenciesStatus = usePanelDependenciesStatus(); 110 return ( 111 <BasePanelStatus definition={definition}> 112 <div className="flex items-center space-x-1"> 113 {panelDependenciesStatus.inputsAwaitingValue.length === 0 && 114 panelDependenciesStatus.total === 0 && ( 115 <> 116 <LoadingIndicator className="w-3.5 h-3.5 text-foreground-light shrink-0" /> 117 <span className="block truncate">Loading...</span> 118 </> 119 )} 120 {panelDependenciesStatus.inputsAwaitingValue.length === 0 && 121 panelDependenciesStatus.total > 0 && ( 122 <> 123 <LoadingIndicator className="w-3.5 h-3.5 text-foreground-light shrink-0" /> 124 <span className="block truncate"> 125 Loading{" "} 126 {panelDependenciesStatus.status.complete.total + 127 panelDependenciesStatus.status.running.total + 128 1}{" "} 129 of {panelDependenciesStatus.total + 1}... 130 </span> 131 </> 132 )} 133 </div> 134 </BasePanelStatus> 135 ); 136 }; 137 138 const PanelCancelled = ({ definition }) => { 139 return ( 140 <BasePanelStatus definition={definition}> 141 <div className="flex items-center space-x-1"> 142 <Icon 143 className="w-3.5 h-3.5 text-foreground-light shrink-0" 144 icon="cancel" 145 /> 146 <span className="block truncate">Cancelled</span> 147 </div> 148 </BasePanelStatus> 149 ); 150 }; 151 152 const PanelError = ({ definition }) => { 153 return ( 154 <BasePanelStatus 155 className="bg-alert-light border-alert text-foreground" 156 definition={definition} 157 > 158 <div className="flex items-center space-x-1"> 159 <Icon 160 className="w-3.5 h-3.5 text-alert shrink-0" 161 icon="materialsymbols-solid:error" 162 /> 163 <span className="block truncate">Error</span> 164 </div> 165 <span className="block"> 166 <ErrorMessage error={definition.error} /> 167 </span> 168 </BasePanelStatus> 169 ); 170 }; 171 172 const PanelStatus = ({ definition, showPanelError }: PanelStatusProps) => ( 173 <> 174 {definition.status === "initialized" && ( 175 <PanelInitialized definition={definition} /> 176 )} 177 {definition.status === "blocked" && ( 178 <PanelBlocked definition={definition} /> 179 )} 180 {definition.status === "running" && ( 181 <PanelRunning definition={definition} /> 182 )} 183 {definition.status === "cancelled" && ( 184 <PanelCancelled definition={definition} /> 185 )} 186 {definition.status === "error" && showPanelError && ( 187 <PanelError definition={definition} /> 188 )} 189 </> 190 ); 191 192 export default PanelStatus;