Merge pull request #1085 from dbeaver/feat/CB-1857-srid-suggest

CB-1857 feat(plugin-gis-viewer): Add combobox for crs selecting
This commit is contained in:
Konstantin Vasilev
2022-08-30 17:26:44 +03:00
committed by GitHub
4 changed files with 119 additions and 19 deletions
@@ -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<TKey, TValue> = Omit<React.InputHTMLAttributes<HTMLInputElement>,
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;
@@ -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)(
<root>
<label>CRS:</label>
<Combobox
items={items}
value={props.value}
onSelect={props.onChange}
/>
</root>
);
}
@@ -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<any, IDatabaseResultSet>;
resultIndex: number;
@@ -87,11 +120,25 @@ export const GISValuePresentation = observer<Props>(function GISValuePresentatio
return values;
}, [view]);
const defaultCrsKey = getCrsKey(parsedGISData[0]);
const [crsKey, setCrsKey] = useState(defaultCrsKey);
if (!parsedGISData.length) {
return <TextPlaceholder>{translate('gis_presentation_placeholder')}</TextPlaceholder>;
}
return (
<LeafletMap geoJSON={parsedGISData} getAssociatedValues={getAssociatedValues} />
return styled(styles)(
<root>
<map>
<LeafletMap key={crsKey} geoJSON={parsedGISData} crsKey={crsKey} getAssociatedValues={getAssociatedValues} />
</map>
<toolbar>
<CrsInput
value={crsKey}
onChange={setCrsKey}
/>
</toolbar>
</root>
);
});
@@ -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<Props> = function LeafletMap({ geoJSON, getAssociatedValues }) {
export const LeafletMap: React.FC<Props> = function LeafletMap({ geoJSON, crsKey, getAssociatedValues }) {
const splitContext = useSplit();
const translate = useTranslate();
const [mapRef, setMapRef] = useState<leaflet.Map | null>(null);
const [geoJSONLayerRef, setGeoJSONLayerRef] = useState<leaflet.GeoJSON | null>(null);
const crs = getCRS(geoJSON[0]);
const crs = getCRS(crsKey);
const onEachFeature = useCallback((feature: IGeoJSONFeature, layer: leaflet.Layer) => {
const associatedValues = getAssociatedValues(feature.properties.associatedCell);