GazetteerPathEditor.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { css } from '@emotion/css';
  2. import React, { FC, useMemo, useState, useEffect } from 'react';
  3. import { StandardEditorProps, SelectableValue, GrafanaTheme2 } from '@grafana/data';
  4. import { Alert, Select, stylesFactory, useTheme2 } from '@grafana/ui';
  5. import { COUNTRIES_GAZETTEER_PATH, Gazetteer, getGazetteer } from '../gazetteer/gazetteer';
  6. const defaultPaths: Array<SelectableValue<string>> = [
  7. {
  8. label: 'Countries',
  9. description: 'Lookup countries by name, two letter code, or three letter code',
  10. value: COUNTRIES_GAZETTEER_PATH,
  11. },
  12. {
  13. label: 'USA States',
  14. description: 'Lookup states by name or 2 ',
  15. value: 'public/gazetteer/usa-states.json',
  16. },
  17. {
  18. label: 'Airports',
  19. description: 'Lookup airports by id or code',
  20. value: 'public/gazetteer/airports.geojson',
  21. },
  22. ];
  23. export interface GazetteerPathEditorConfigSettings {
  24. options?: Array<SelectableValue<string>>;
  25. }
  26. export const GazetteerPathEditor: FC<StandardEditorProps<string, any, any, GazetteerPathEditorConfigSettings>> = ({
  27. value,
  28. onChange,
  29. context,
  30. item,
  31. }) => {
  32. const styles = getStyles(useTheme2());
  33. const [gaz, setGaz] = useState<Gazetteer>();
  34. const settings = item.settings as any;
  35. useEffect(() => {
  36. async function fetchData() {
  37. const p = await getGazetteer(value);
  38. setGaz(p);
  39. }
  40. fetchData();
  41. }, [value, setGaz]);
  42. const { current, options } = useMemo(() => {
  43. let options = settings?.options ? [...settings.options] : [...defaultPaths];
  44. let current = options?.find((f) => f.value === gaz?.path);
  45. if (!current && gaz) {
  46. current = {
  47. label: gaz.path,
  48. value: gaz.path,
  49. };
  50. options.push(current);
  51. }
  52. return { options, current };
  53. }, [gaz, settings?.options]);
  54. return (
  55. <>
  56. <Select
  57. value={current}
  58. options={options}
  59. onChange={(v) => onChange(v.value)}
  60. allowCustomValue={true}
  61. formatCreateLabel={(txt) => `Load from URL: ${txt}`}
  62. />
  63. {gaz && (
  64. <>
  65. {gaz.error && <Alert title={gaz.error} severity={'warning'} />}
  66. {gaz.count && (
  67. <div className={styles.keys}>
  68. <b>({gaz.count})</b>
  69. {gaz.examples(10).map((k) => (
  70. <span key={k}>{k},</span>
  71. ))}
  72. {gaz.count > 10 && ' ...'}
  73. </div>
  74. )}
  75. </>
  76. )}
  77. </>
  78. );
  79. };
  80. const getStyles = stylesFactory((theme: GrafanaTheme2) => {
  81. return {
  82. keys: css`
  83. margin-top: 4px;
  84. text-overflow: ellipsis;
  85. overflow: hidden;
  86. white-space: nowrap;
  87. > span {
  88. margin-left: 4px;
  89. }
  90. `,
  91. };
  92. });