Submit
Path:
~
/
/
usr
/
share
/
grafana
/
public
/
app
/
plugins
/
panel
/
geomap
/
components
/
File Content:
MeasureOverlay.tsx
import { css } from '@emotion/css'; import Map from 'ol/Map'; import React, { useMemo, useRef, useState } from 'react'; import { GrafanaTheme2, SelectableValue } from '@grafana/data'; import { Button, IconButton, RadioButtonGroup, Select } from '@grafana/ui'; import { config } from 'app/core/config'; import { MapMeasure, MapMeasureOptions, measures } from '../utils/measure'; import { MeasureVectorLayer } from './MeasureVectorLayer'; type Props = { map: Map; menuActiveState: (value: boolean) => void; }; export const MeasureOverlay = ({ map, menuActiveState }: Props) => { const vector = useRef(new MeasureVectorLayer()); const measureStyle = getStyles(config.theme2); // Menu State Management const [firstLoad, setFirstLoad] = useState<boolean>(true); const [menuActive, setMenuActive] = useState<boolean>(false); // Options State const [options, setOptions] = useState<MapMeasureOptions>({ action: measures[0].value!, unit: measures[0].units[0].value!, }); const unit = useMemo(() => { const action = measures.find((m: MapMeasure) => m.value === options.action) ?? measures[0]; const current = action.getUnit(options.unit); vector.current.setOptions(options); return { current, options: action.units, }; }, [options]); const clearPrevious = true; const showSegments = false; function toggleMenu() { setMenuActive(!menuActive); // Lift menu state // TODO: consolidate into one state menuActiveState(!menuActive); if (menuActive) { map.removeInteraction(vector.current.draw); vector.current.setVisible(false); } else { if (firstLoad) { // Initialize on first load setFirstLoad(false); vector.current.setZIndex(1); map.addLayer(vector.current); map.addInteraction(vector.current.modify); } vector.current.setVisible(true); map.removeInteraction(vector.current.draw); // Remove last interaction const a = measures.find((v: MapMeasure) => v.value === options.action) ?? measures[0]; vector.current.addInteraction(map, a.geometry, showSegments, clearPrevious); } } return ( <div className={`${measureStyle.infoWrap} ${!menuActive ? measureStyle.infoWrapClosed : null}`}> {menuActive ? ( <div> <div className={measureStyle.rowGroup}> <RadioButtonGroup value={options.action} options={measures} size="md" fullWidth={false} onChange={(e: string) => { map.removeInteraction(vector.current.draw); const m = measures.find((v: MapMeasure) => v.value === e) ?? measures[0]; const unit = m.getUnit(options.unit); setOptions({ ...options, action: m.value!, unit: unit.value! }); vector.current.addInteraction(map, m.geometry, showSegments, clearPrevious); }} /> <Button className={measureStyle.button} icon="times" variant="secondary" size="sm" onClick={toggleMenu} /> </div> <Select className={measureStyle.unitSelect} value={unit.current} options={unit.options} isSearchable={false} onChange={(v: SelectableValue<string>) => { const a = measures.find((v: SelectableValue<string>) => v.value === options.action) ?? measures[0]; const unit = a.getUnit(v.value) ?? a.units[0]; setOptions({ ...options, unit: unit.value! }); }} /> </div> ) : ( <IconButton className={measureStyle.icon} name="ruler-combined" tooltip="show measure tools" tooltipPlacement="left" onClick={toggleMenu} /> )} </div> ); }; const getStyles = (theme: GrafanaTheme2) => ({ button: css({ marginLeft: 'auto', }), icon: css({ backgroundColor: theme.colors.secondary.main, display: 'inline-block', height: '19.25px', margin: '1px', width: '19.25px', }), infoWrap: css({ color: `${theme.colors.text}`, backgroundColor: theme.colors.background.secondary, // eslint-disable-next-line @grafana/no-border-radius-literal borderRadius: '4px', padding: '2px', }), infoWrapClosed: css({ height: '25.25px', width: '25.25px', }), rowGroup: css({ display: 'flex', justifyContent: 'flex-end', }), unitSelect: css({ minWidth: '200px', }), });
Edit
Rename
Chmod
Delete
FILE
FOLDER
INFO
Name
Size
Permission
Action
DebugOverlay.tsx
1811 bytes
0644
MarkersLegend.tsx
5364 bytes
0644
MeasureOverlay.tsx
4541 bytes
0644
MeasureVectorLayer.ts
7111 bytes
0644
ObservablePropsWrapper.tsx
873 bytes
0644
N4ST4R_ID | Naxtarrr