diff --git a/webapp/packages/core-blocks/src/FormControls/Combobox.tsx b/webapp/packages/core-blocks/src/FormControls/Combobox.tsx index 9c7fdc5ba4..b82dbb201f 100644 --- a/webapp/packages/core-blocks/src/FormControls/Combobox.tsx +++ b/webapp/packages/core-blocks/src/FormControls/Combobox.tsx @@ -90,7 +90,7 @@ const styles = css` width: 100%; height: 100%; } - } + } } } Icon { @@ -112,12 +112,12 @@ const styles = css` width: 16px; height: 16px; margin-left: 12px; - + & IconOrImage { width: 100%; height: 100%; } - + &:not(:empty) + input { padding-left: 34px !important; } @@ -131,8 +131,8 @@ type BaseProps = Omit, searchable?: boolean; defaultValue?: TKey; loading?: boolean; - keySelector: (item: TValue, index: number) => TKey; - valueSelector: (item: TValue) => string; + keySelector?: (item: TValue, index: number) => TKey; + valueSelector?: (item: TValue) => string; titleSelector?: (item: TValue) => string | undefined; iconSelector?: (item: TValue) => string | React.ReactElement | undefined; isDisabled?: (item: TValue) => boolean; diff --git a/webapp/packages/plugin-gis-viewer/src/CrsInput.tsx b/webapp/packages/plugin-gis-viewer/src/CrsInput.tsx new file mode 100644 index 0000000000..d3e4836764 --- /dev/null +++ b/webapp/packages/plugin-gis-viewer/src/CrsInput.tsx @@ -0,0 +1,50 @@ +import styled, { css } from 'reshadow'; + +import { Combobox } from '@cloudbeaver/core-blocks'; + +import type { CrsKey } from './LeafletMap'; + +const styles = css` + root { + display: inline-flex; + align-items: center; + font-size: 12px; + } + + label { + margin-right: 4px; + flex-grow: 0; + flex-shrink: 1; + } + + Combobox { + width: 120px; + flex: 0 0 auto; + } +`; + +interface Props { + value: CrsKey; + onChange: (value: CrsKey) => void; +} + +const items: CrsKey[] = [ + 'Simple', + 'EPSG3395', + 'EPSG3857', + 'EPSG4326', + 'EPSG900913', +]; + +export function CrsInput(props: Props) { + return styled(styles)( + + + + + ); +} \ No newline at end of file diff --git a/webapp/packages/plugin-gis-viewer/src/GISValuePresentation.tsx b/webapp/packages/plugin-gis-viewer/src/GISValuePresentation.tsx index 43e5322b1b..1c97f0ff2d 100644 --- a/webapp/packages/plugin-gis-viewer/src/GISValuePresentation.tsx +++ b/webapp/packages/plugin-gis-viewer/src/GISValuePresentation.tsx @@ -5,18 +5,51 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ - import { observer } from 'mobx-react-lite'; -import { useCallback, useMemo } from 'react'; +import { useCallback, useMemo, useState } from 'react'; +import styled, { css } from 'reshadow'; import wellknown from 'wellknown'; import { TextPlaceholder } from '@cloudbeaver/core-blocks'; import { useTranslate } from '@cloudbeaver/core-localization'; import { IDatabaseResultSet, ResultSetSelectAction, IResultSetElementKey, IDatabaseDataModel, ResultSetViewAction, ResultSetDataKeysUtils } from '@cloudbeaver/plugin-data-viewer'; -import { IGeoJSONFeature, IAssociatedValue, LeafletMap } from './LeafletMap'; +import { CrsInput } from './CrsInput'; +import { IGeoJSONFeature, IAssociatedValue, LeafletMap, CrsKey } from './LeafletMap'; import { ResultSetGISAction } from './ResultSetGISAction'; +function getCrsKey(feature?: IGeoJSONFeature): CrsKey { + switch (feature?.properties.srid) { + case 3857: + return 'EPSG3857'; + case 4326: + return 'EPSG4326'; + case 3395: + return 'EPSG3395'; + case 900913: + return 'EPSG900913'; + default: + return 'EPSG3857'; + } +} + +const styles = css` + root { + display: flex; + flex-direction: column; + width: 100%; + } + + map { + flex: 1 1 auto; + } + + toolbar { + margin-top: 8px; + flex: 0 0 auto; + } +`; + interface Props { model: IDatabaseDataModel; resultIndex: number; @@ -87,11 +120,25 @@ export const GISValuePresentation = observer(function GISValuePresentatio return values; }, [view]); + + const defaultCrsKey = getCrsKey(parsedGISData[0]); + const [crsKey, setCrsKey] = useState(defaultCrsKey); + if (!parsedGISData.length) { return {translate('gis_presentation_placeholder')}; } - return ( - + return styled(styles)( + + + + + + + + ); }); diff --git a/webapp/packages/plugin-gis-viewer/src/LeafletMap.tsx b/webapp/packages/plugin-gis-viewer/src/LeafletMap.tsx index bff6d0153f..0a7673ae2b 100644 --- a/webapp/packages/plugin-gis-viewer/src/LeafletMap.tsx +++ b/webapp/packages/plugin-gis-viewer/src/LeafletMap.tsx @@ -42,8 +42,11 @@ interface IBaseTile extends TileLayerProps { checked?: boolean; } +export type CrsKey = 'Simple' | 'EPSG3857' | 'EPSG4326' | 'EPSG3395' | 'EPSG900913'; + interface Props { geoJSON: IGeoJSONFeature[]; + crsKey: CrsKey; getAssociatedValues: (cell: IResultSetElementKey) => IAssociatedValue[]; } @@ -87,17 +90,17 @@ function polyStyle() { }; } -function getCRS(feature?: IGeoJSONFeature): leaflet.CRS { - switch (feature?.properties.srid) { - case 0: +function getCRS(crsKey: CrsKey): leaflet.CRS { + switch (crsKey) { + case 'Simple': return leaflet.CRS.Simple; - case 3857: + case 'EPSG3857': return leaflet.CRS.EPSG3857; - case 4326: + case 'EPSG4326': return leaflet.CRS.EPSG4326; - case 3395: + case 'EPSG3395': return leaflet.CRS.EPSG3395; - case 900913: + case 'EPSG900913': return leaflet.CRS.EPSG900913; default: return leaflet.CRS.EPSG3857; @@ -111,14 +114,14 @@ const styles = css` } `; -export const LeafletMap: React.FC = function LeafletMap({ geoJSON, getAssociatedValues }) { +export const LeafletMap: React.FC = function LeafletMap({ geoJSON, crsKey, getAssociatedValues }) { const splitContext = useSplit(); const translate = useTranslate(); const [mapRef, setMapRef] = useState(null); const [geoJSONLayerRef, setGeoJSONLayerRef] = useState(null); - const crs = getCRS(geoJSON[0]); + const crs = getCRS(crsKey); const onEachFeature = useCallback((feature: IGeoJSONFeature, layer: leaflet.Layer) => { const associatedValues = getAssociatedValues(feature.properties.associatedCell);