DataHoverRows.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import { css } from '@emotion/css';
  2. import { isString } from 'lodash';
  3. import { FeatureLike } from 'ol/Feature';
  4. import React, { useState } from 'react';
  5. import { DataFrame, FieldType, getFieldDisplayName, GrafanaTheme2 } from '@grafana/data';
  6. import { Collapse, TabContent, useStyles2 } from '@grafana/ui';
  7. import { GeomapLayerHover } from '../event';
  8. import { DataHoverRow } from './DataHoverRow';
  9. type Props = {
  10. layers: GeomapLayerHover[];
  11. activeTabIndex: number;
  12. };
  13. export const DataHoverRows = ({ layers, activeTabIndex }: Props) => {
  14. const styles = useStyles2(getStyles);
  15. const [rowMap, setRowMap] = useState(new Map<string | number, boolean>());
  16. const updateRowMap = (key: string | number, value: boolean) => {
  17. setRowMap(new Map(rowMap.set(key, value)));
  18. };
  19. return (
  20. <TabContent>
  21. {layers.map(
  22. (geomapLayer, index) =>
  23. index === activeTabIndex && (
  24. <div key={geomapLayer.layer.getName()}>
  25. <div>
  26. {geomapLayer.features.map((feature, idx) => {
  27. const key = feature.getId() ?? idx;
  28. const shouldDisplayCollapse = geomapLayer.features.length > 1;
  29. return shouldDisplayCollapse ? (
  30. <Collapse
  31. key={key}
  32. collapsible
  33. label={generateLabel(feature, idx)}
  34. isOpen={rowMap.get(key)}
  35. onToggle={() => {
  36. updateRowMap(key, !rowMap.get(key));
  37. }}
  38. className={styles.collapsibleRow}
  39. >
  40. <DataHoverRow feature={feature} />
  41. </Collapse>
  42. ) : (
  43. <DataHoverRow key={key} feature={feature} />
  44. );
  45. })}
  46. </div>
  47. </div>
  48. )
  49. )}
  50. </TabContent>
  51. );
  52. };
  53. export const generateLabel = (feature: FeatureLike, idx: number): string => {
  54. const names = ['Name', 'name', 'Title', 'ID', 'id'];
  55. let props = feature.getProperties();
  56. let first = '';
  57. const frame = feature.get('frame') as DataFrame;
  58. if (frame) {
  59. const rowIndex = feature.get('rowIndex');
  60. for (const f of frame.fields) {
  61. if (f.type === FieldType.string) {
  62. const k = getFieldDisplayName(f, frame);
  63. if (!first) {
  64. first = k;
  65. }
  66. props[k] = f.values.get(rowIndex);
  67. }
  68. }
  69. }
  70. for (let k of names) {
  71. const v = props[k];
  72. if (v) {
  73. return v;
  74. }
  75. }
  76. if (first) {
  77. return `${first}: ${props[first]}`;
  78. }
  79. for (let k of Object.keys(props)) {
  80. const v = props[k];
  81. if (isString(v)) {
  82. return `${k}: ${v}`;
  83. }
  84. }
  85. return `Match: ${idx + 1}`;
  86. };
  87. const getStyles = (theme: GrafanaTheme2) => ({
  88. collapsibleRow: css`
  89. margin-bottom: 0px;
  90. `,
  91. });