| 
									
										
										
										
											2022-04-22 21:33:13 +08:00
										 |  |  | import { css } from '@emotion/css'; | 
					
						
							| 
									
										
										
										
											2021-03-31 23:56:15 +08:00
										 |  |  | import cx from 'classnames'; | 
					
						
							| 
									
										
										
										
											2024-06-25 19:43:47 +08:00
										 |  |  | import { MouseEvent, memo } from 'react'; | 
					
						
							| 
									
										
										
										
											2022-04-22 21:33:13 +08:00
										 |  |  | import tinycolor from 'tinycolor2'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-18 22:30:27 +08:00
										 |  |  | import { Field, getFieldColorModeForField, GrafanaTheme2 } from '@grafana/data'; | 
					
						
							| 
									
										
										
										
											2025-05-30 01:13:25 +08:00
										 |  |  | import { useTranslate } from '@grafana/i18n'; | 
					
						
							| 
									
										
										
										
											2023-03-01 23:02:33 +08:00
										 |  |  | import { Icon, useTheme2 } from '@grafana/ui'; | 
					
						
							| 
									
										
										
										
											2022-04-22 21:33:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-12 20:14:45 +08:00
										 |  |  | import { HoverState } from './NodeGraph'; | 
					
						
							| 
									
										
										
										
											2021-03-31 23:56:15 +08:00
										 |  |  | import { NodeDatum } from './types'; | 
					
						
							| 
									
										
										
										
											2021-05-12 22:04:21 +08:00
										 |  |  | import { statToString } from './utils'; | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-25 22:55:52 +08:00
										 |  |  | export const nodeR = 40; | 
					
						
							| 
									
										
										
										
											2023-10-24 21:16:10 +08:00
										 |  |  | export const highlightedNodeColor = '#a00'; | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-12 20:14:45 +08:00
										 |  |  | const getStyles = (theme: GrafanaTheme2, hovering: HoverState) => ({ | 
					
						
							| 
									
										
										
										
											2024-10-25 21:50:28 +08:00
										 |  |  |   mainGroup: css({ | 
					
						
							|  |  |  |     cursor: 'pointer', | 
					
						
							|  |  |  |     fontSize: '10px', | 
					
						
							|  |  |  |     [theme.transitions.handleMotion('no-preference', 'reduce')]: { | 
					
						
							|  |  |  |       transition: 'opacity 300ms', | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     opacity: hovering === 'inactive' ? 0.5 : 1, | 
					
						
							|  |  |  |   }), | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-25 21:50:28 +08:00
										 |  |  |   mainCircle: css({ | 
					
						
							|  |  |  |     fill: theme.components.panel.background, | 
					
						
							|  |  |  |   }), | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-25 21:50:28 +08:00
										 |  |  |   filledCircle: css({ | 
					
						
							|  |  |  |     fill: highlightedNodeColor, | 
					
						
							|  |  |  |   }), | 
					
						
							| 
									
										
										
										
											2023-10-24 21:16:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-25 21:50:28 +08:00
										 |  |  |   hoverCircle: css({ | 
					
						
							|  |  |  |     opacity: 0.5, | 
					
						
							|  |  |  |     fill: 'transparent', | 
					
						
							|  |  |  |     stroke: theme.colors.primary.text, | 
					
						
							|  |  |  |   }), | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-25 21:50:28 +08:00
										 |  |  |   text: css({ | 
					
						
							|  |  |  |     fill: theme.colors.text.primary, | 
					
						
							|  |  |  |     pointerEvents: 'none', | 
					
						
							|  |  |  |   }), | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-25 21:50:28 +08:00
										 |  |  |   titleText: css({ | 
					
						
							|  |  |  |     textAlign: 'center', | 
					
						
							|  |  |  |     textOverflow: 'ellipsis', | 
					
						
							|  |  |  |     overflow: 'hidden', | 
					
						
							|  |  |  |     whiteSpace: 'nowrap', | 
					
						
							|  |  |  |     backgroundColor: tinycolor(theme.colors.background.primary).setAlpha(0.6).toHex8String(), | 
					
						
							|  |  |  |     width: '140px', | 
					
						
							|  |  |  |   }), | 
					
						
							| 
									
										
										
										
											2021-03-31 23:56:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-25 21:50:28 +08:00
										 |  |  |   statsText: css({ | 
					
						
							|  |  |  |     textAlign: 'center', | 
					
						
							|  |  |  |     textOverflow: 'ellipsis', | 
					
						
							|  |  |  |     overflow: 'hidden', | 
					
						
							|  |  |  |     whiteSpace: 'nowrap', | 
					
						
							|  |  |  |     width: '70px', | 
					
						
							|  |  |  |   }), | 
					
						
							| 
									
										
										
										
											2021-03-31 23:56:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-25 21:50:28 +08:00
										 |  |  |   textHovering: css({ | 
					
						
							|  |  |  |     width: '200px', | 
					
						
							|  |  |  |     '& span': { | 
					
						
							|  |  |  |       backgroundColor: tinycolor(theme.colors.background.primary).setAlpha(0.8).toHex8String(), | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }), | 
					
						
							| 
									
										
										
										
											2023-05-17 21:22:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-25 21:50:28 +08:00
										 |  |  |   clickTarget: css({ | 
					
						
							|  |  |  |     fill: 'none', | 
					
						
							|  |  |  |     stroke: 'none', | 
					
						
							|  |  |  |     pointerEvents: 'fill', | 
					
						
							|  |  |  |   }), | 
					
						
							| 
									
										
										
										
											2021-05-12 22:04:21 +08:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-24 21:16:10 +08:00
										 |  |  | export const computeNodeCircumferenceStrokeWidth = (nodeRadius: number) => Math.ceil(nodeRadius * 0.075); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  | export const Node = memo(function Node(props: { | 
					
						
							|  |  |  |   node: NodeDatum; | 
					
						
							| 
									
										
										
										
											2023-03-01 23:02:33 +08:00
										 |  |  |   hovering: HoverState; | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  |   onMouseEnter: (id: string) => void; | 
					
						
							|  |  |  |   onMouseLeave: (id: string) => void; | 
					
						
							|  |  |  |   onClick: (event: MouseEvent<SVGElement>, node: NodeDatum) => void; | 
					
						
							|  |  |  | }) { | 
					
						
							| 
									
										
										
										
											2025-05-30 01:13:25 +08:00
										 |  |  |   const { t } = useTranslate(); | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  |   const { node, onMouseEnter, onMouseLeave, onClick, hovering } = props; | 
					
						
							| 
									
										
										
										
											2022-07-12 20:14:45 +08:00
										 |  |  |   const theme = useTheme2(); | 
					
						
							|  |  |  |   const styles = getStyles(theme, hovering); | 
					
						
							|  |  |  |   const isHovered = hovering === 'active'; | 
					
						
							| 
									
										
										
										
											2023-09-25 22:55:52 +08:00
										 |  |  |   const nodeRadius = node.nodeRadius?.values[node.dataFrameRowIndex] || nodeR; | 
					
						
							| 
									
										
										
										
											2023-10-24 21:16:10 +08:00
										 |  |  |   const strokeWidth = computeNodeCircumferenceStrokeWidth(nodeRadius); | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!(node.x !== undefined && node.y !== undefined)) { | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ( | 
					
						
							| 
									
										
										
										
											2025-05-30 01:13:25 +08:00
										 |  |  |     <g | 
					
						
							|  |  |  |       data-node-id={node.id} | 
					
						
							|  |  |  |       className={styles.mainGroup} | 
					
						
							|  |  |  |       aria-label={t('nodeGraph.node.aria-label-node-title', 'Node: {{nodeName}}', { nodeName: node.title })} | 
					
						
							|  |  |  |     > | 
					
						
							| 
									
										
										
										
											2023-09-25 22:55:52 +08:00
										 |  |  |       <circle | 
					
						
							|  |  |  |         data-testid={`node-circle-${node.id}`} | 
					
						
							| 
									
										
										
										
											2023-10-24 21:16:10 +08:00
										 |  |  |         className={node.highlighted ? styles.filledCircle : styles.mainCircle} | 
					
						
							| 
									
										
										
										
											2023-09-25 22:55:52 +08:00
										 |  |  |         r={nodeRadius} | 
					
						
							|  |  |  |         cx={node.x} | 
					
						
							|  |  |  |         cy={node.y} | 
					
						
							|  |  |  |       /> | 
					
						
							|  |  |  |       {isHovered && ( | 
					
						
							| 
									
										
										
										
											2023-10-24 21:16:10 +08:00
										 |  |  |         <circle className={styles.hoverCircle} r={nodeRadius - 3} cx={node.x} cy={node.y} strokeWidth={strokeWidth} /> | 
					
						
							| 
									
										
										
										
											2023-09-25 22:55:52 +08:00
										 |  |  |       )} | 
					
						
							| 
									
										
										
										
											2021-03-31 23:56:15 +08:00
										 |  |  |       <ColorCircle node={node} /> | 
					
						
							| 
									
										
										
										
											2023-05-17 21:22:21 +08:00
										 |  |  |       <g className={styles.text} style={{ pointerEvents: 'none' }}> | 
					
						
							| 
									
										
										
										
											2023-03-01 23:02:33 +08:00
										 |  |  |         <NodeContents node={node} hovering={hovering} /> | 
					
						
							| 
									
										
										
										
											2021-03-31 23:56:15 +08:00
										 |  |  |         <foreignObject | 
					
						
							| 
									
										
										
										
											2023-07-18 18:11:12 +08:00
										 |  |  |           x={node.x - (isHovered ? 100 : 70)} | 
					
						
							| 
									
										
										
										
											2023-09-25 22:55:52 +08:00
										 |  |  |           y={node.y + nodeRadius + 5} | 
					
						
							| 
									
										
										
										
											2023-07-18 18:11:12 +08:00
										 |  |  |           width={isHovered ? '200' : '140'} | 
					
						
							| 
									
										
										
										
											2021-11-07 14:13:14 +08:00
										 |  |  |           height="40" | 
					
						
							| 
									
										
										
										
											2021-03-31 23:56:15 +08:00
										 |  |  |         > | 
					
						
							| 
									
										
										
										
											2022-07-12 20:14:45 +08:00
										 |  |  |           <div className={cx(styles.titleText, isHovered && styles.textHovering)}> | 
					
						
							| 
									
										
										
										
											2021-03-31 23:56:15 +08:00
										 |  |  |             <span>{node.title}</span> | 
					
						
							|  |  |  |             <br /> | 
					
						
							|  |  |  |             <span>{node.subTitle}</span> | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  |           </div> | 
					
						
							|  |  |  |         </foreignObject> | 
					
						
							|  |  |  |       </g> | 
					
						
							| 
									
										
										
										
											2023-05-17 21:22:21 +08:00
										 |  |  |       <rect | 
					
						
							|  |  |  |         data-testid={`node-click-rect-${node.id}`} | 
					
						
							|  |  |  |         onMouseEnter={() => { | 
					
						
							|  |  |  |           onMouseEnter(node.id); | 
					
						
							|  |  |  |         }} | 
					
						
							|  |  |  |         onMouseLeave={() => { | 
					
						
							|  |  |  |           onMouseLeave(node.id); | 
					
						
							|  |  |  |         }} | 
					
						
							|  |  |  |         onClick={(event) => { | 
					
						
							|  |  |  |           onClick(event, node); | 
					
						
							|  |  |  |         }} | 
					
						
							|  |  |  |         className={styles.clickTarget} | 
					
						
							| 
									
										
										
										
											2023-09-25 22:55:52 +08:00
										 |  |  |         x={node.x - nodeRadius - 5} | 
					
						
							|  |  |  |         y={node.y - nodeRadius - 5} | 
					
						
							|  |  |  |         width={nodeRadius * 2 + 10} | 
					
						
							|  |  |  |         height={nodeRadius * 2 + 50} | 
					
						
							| 
									
										
										
										
											2023-05-17 21:22:21 +08:00
										 |  |  |       /> | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  |     </g> | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-01 23:02:33 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Shows contents of the node which can be either an Icon or a main and secondary stat values. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function NodeContents({ node, hovering }: { node: NodeDatum; hovering: HoverState }) { | 
					
						
							|  |  |  |   const theme = useTheme2(); | 
					
						
							|  |  |  |   const styles = getStyles(theme, hovering); | 
					
						
							|  |  |  |   const isHovered = hovering === 'active'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!(node.x !== undefined && node.y !== undefined)) { | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return node.icon ? ( | 
					
						
							|  |  |  |     <foreignObject x={node.x - 35} y={node.y - 20} width="70" height="40"> | 
					
						
							|  |  |  |       <div style={{ width: 70, overflow: 'hidden', display: 'flex', justifyContent: 'center', marginTop: -4 }}> | 
					
						
							|  |  |  |         <Icon data-testid={`node-icon-${node.icon}`} name={node.icon} size={'xxxl'} /> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |     </foreignObject> | 
					
						
							|  |  |  |   ) : ( | 
					
						
							|  |  |  |     <foreignObject x={node.x - (isHovered ? 100 : 35)} y={node.y - 15} width={isHovered ? '200' : '70'} height="40"> | 
					
						
							|  |  |  |       <div className={cx(styles.statsText, isHovered && styles.textHovering)}> | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |         <span>{node.mainStat && statToString(node.mainStat.config, node.mainStat.values[node.dataFrameRowIndex])}</span> | 
					
						
							| 
									
										
										
										
											2023-03-01 23:02:33 +08:00
										 |  |  |         <br /> | 
					
						
							|  |  |  |         <span> | 
					
						
							|  |  |  |           {node.secondaryStat && | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |             statToString(node.secondaryStat.config, node.secondaryStat.values[node.dataFrameRowIndex])} | 
					
						
							| 
									
										
										
										
											2023-03-01 23:02:33 +08:00
										 |  |  |         </span> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |     </foreignObject> | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2021-03-31 23:56:15 +08:00
										 |  |  |  * Shows the outer segmented circle with different colors based on the supplied data. | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-03-31 23:56:15 +08:00
										 |  |  | function ColorCircle(props: { node: NodeDatum }) { | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  |   const { node } = props; | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |   const fullStat = node.arcSections.find((s) => s.values[node.dataFrameRowIndex] >= 1); | 
					
						
							| 
									
										
										
										
											2021-05-18 22:30:27 +08:00
										 |  |  |   const theme = useTheme2(); | 
					
						
							| 
									
										
										
										
											2023-09-25 22:55:52 +08:00
										 |  |  |   const nodeRadius = node.nodeRadius?.values[node.dataFrameRowIndex] || nodeR; | 
					
						
							| 
									
										
										
										
											2023-10-24 21:16:10 +08:00
										 |  |  |   const strokeWidth = computeNodeCircumferenceStrokeWidth(nodeRadius); | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (fullStat) { | 
					
						
							| 
									
										
										
										
											2023-10-24 21:16:10 +08:00
										 |  |  |     // Drawing a full circle with a `path` tag does not work well, it's better to use a `circle` tag in that case
 | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  |     return ( | 
					
						
							|  |  |  |       <circle | 
					
						
							|  |  |  |         fill="none" | 
					
						
							| 
									
										
										
										
											2021-05-18 22:30:27 +08:00
										 |  |  |         stroke={theme.visualization.getColorByName(fullStat.config.color?.fixedColor || '')} | 
					
						
							| 
									
										
										
										
											2023-10-24 21:16:10 +08:00
										 |  |  |         strokeWidth={strokeWidth} | 
					
						
							| 
									
										
										
										
											2023-09-25 22:55:52 +08:00
										 |  |  |         r={nodeRadius} | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  |         cx={node.x} | 
					
						
							|  |  |  |         cy={node.y} | 
					
						
							|  |  |  |       /> | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |   const nonZero = node.arcSections.filter((s) => s.values[node.dataFrameRowIndex] !== 0); | 
					
						
							| 
									
										
										
										
											2021-03-31 23:56:15 +08:00
										 |  |  |   if (nonZero.length === 0) { | 
					
						
							|  |  |  |     // Fallback if no arc is defined
 | 
					
						
							| 
									
										
										
										
											2021-05-18 22:30:27 +08:00
										 |  |  |     return ( | 
					
						
							|  |  |  |       <circle | 
					
						
							|  |  |  |         fill="none" | 
					
						
							|  |  |  |         stroke={node.color ? getColor(node.color, node.dataFrameRowIndex, theme) : 'gray'} | 
					
						
							| 
									
										
										
										
											2023-10-24 21:16:10 +08:00
										 |  |  |         strokeWidth={strokeWidth} | 
					
						
							| 
									
										
										
										
											2023-09-25 22:55:52 +08:00
										 |  |  |         r={nodeRadius} | 
					
						
							| 
									
										
										
										
											2021-05-18 22:30:27 +08:00
										 |  |  |         cx={node.x} | 
					
						
							|  |  |  |         cy={node.y} | 
					
						
							|  |  |  |       /> | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2021-03-31 23:56:15 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-24 00:54:57 +08:00
										 |  |  |   const { elements } = nonZero.reduce<{ | 
					
						
							|  |  |  |     elements: React.ReactNode[]; | 
					
						
							|  |  |  |     percent: number; | 
					
						
							|  |  |  |   }>( | 
					
						
							| 
									
										
										
										
											2023-03-01 23:02:33 +08:00
										 |  |  |     (acc, section, index) => { | 
					
						
							| 
									
										
										
										
											2021-05-12 22:04:21 +08:00
										 |  |  |       const color = section.config.color?.fixedColor || ''; | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |       const value = section.values[node.dataFrameRowIndex]; | 
					
						
							| 
									
										
										
										
											2022-10-24 17:28:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  |       const el = ( | 
					
						
							|  |  |  |         <ArcSection | 
					
						
							| 
									
										
										
										
											2023-03-01 23:02:33 +08:00
										 |  |  |           key={index} | 
					
						
							| 
									
										
										
										
											2023-09-25 22:55:52 +08:00
										 |  |  |           r={nodeRadius} | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  |           x={node.x!} | 
					
						
							|  |  |  |           y={node.y!} | 
					
						
							|  |  |  |           startPercent={acc.percent} | 
					
						
							| 
									
										
										
										
											2022-10-24 17:28:49 +08:00
										 |  |  |           percent={ | 
					
						
							|  |  |  |             value + acc.percent > 1 | 
					
						
							|  |  |  |               ? // If the values aren't correct and add up to more than 100% lets still render correctly the amounts we
 | 
					
						
							|  |  |  |                 // already have and cap it at 100%
 | 
					
						
							|  |  |  |                 1 - acc.percent | 
					
						
							|  |  |  |               : value | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2021-05-18 22:30:27 +08:00
										 |  |  |           color={theme.visualization.getColorByName(color)} | 
					
						
							| 
									
										
										
										
											2023-10-24 21:16:10 +08:00
										 |  |  |           strokeWidth={strokeWidth} | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  |         /> | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |       acc.elements.push(el); | 
					
						
							| 
									
										
										
										
											2021-05-12 22:04:21 +08:00
										 |  |  |       acc.percent = acc.percent + value; | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  |       return acc; | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2022-11-24 00:54:57 +08:00
										 |  |  |     { elements: [], percent: 0 } | 
					
						
							| 
									
										
										
										
											2021-01-19 23:34:43 +08:00
										 |  |  |   ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return <>{elements}</>; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function ArcSection({ | 
					
						
							|  |  |  |   r, | 
					
						
							|  |  |  |   x, | 
					
						
							|  |  |  |   y, | 
					
						
							|  |  |  |   startPercent, | 
					
						
							|  |  |  |   percent, | 
					
						
							|  |  |  |   color, | 
					
						
							|  |  |  |   strokeWidth = 2, | 
					
						
							|  |  |  | }: { | 
					
						
							|  |  |  |   r: number; | 
					
						
							|  |  |  |   x: number; | 
					
						
							|  |  |  |   y: number; | 
					
						
							|  |  |  |   startPercent: number; | 
					
						
							|  |  |  |   percent: number; | 
					
						
							|  |  |  |   color: string; | 
					
						
							|  |  |  |   strokeWidth?: number; | 
					
						
							|  |  |  | }) { | 
					
						
							|  |  |  |   const endPercent = startPercent + percent; | 
					
						
							|  |  |  |   const startXPos = x + Math.sin(2 * Math.PI * startPercent) * r; | 
					
						
							|  |  |  |   const startYPos = y - Math.cos(2 * Math.PI * startPercent) * r; | 
					
						
							|  |  |  |   const endXPos = x + Math.sin(2 * Math.PI * endPercent) * r; | 
					
						
							|  |  |  |   const endYPos = y - Math.cos(2 * Math.PI * endPercent) * r; | 
					
						
							|  |  |  |   const largeArc = percent > 0.5 ? '1' : '0'; | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <path | 
					
						
							|  |  |  |       fill="none" | 
					
						
							|  |  |  |       d={`M ${startXPos} ${startYPos} A ${r} ${r} 0 ${largeArc} 1 ${endXPos} ${endYPos}`} | 
					
						
							|  |  |  |       stroke={color} | 
					
						
							|  |  |  |       strokeWidth={strokeWidth} | 
					
						
							|  |  |  |     /> | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-05-18 22:30:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | function getColor(field: Field, index: number, theme: GrafanaTheme2): string { | 
					
						
							|  |  |  |   if (!field.config.color) { | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |     return field.values[index]; | 
					
						
							| 
									
										
										
										
											2021-05-18 22:30:27 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-18 05:46:29 +08:00
										 |  |  |   return getFieldColorModeForField(field).getCalculator(field, theme)(0, field.values[index]); | 
					
						
							| 
									
										
										
										
											2021-05-18 22:30:27 +08:00
										 |  |  | } |