Skip to content

Commit

Permalink
Merge branch 'devel' into CB-4257-ability-to-assume-aws-session-using…
Browse files Browse the repository at this point in the history
…-any-open-id-provider
  • Loading branch information
dariamarutkina authored Jan 30, 2024
2 parents c6b152f + cd7ffe6 commit b663564
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -433,9 +433,9 @@ private String renameConnectionFolder(@NotNull WebSession session, DBNNode node,
if (siblings.contains(newName)) {
throw new DBWebException("Name " + newName + " is unavailable or invalid");
}
var oldNodePath = node.getNodeUri();
var oldNodePath = node.getNodeItemPath();
node.rename(session.getProgressMonitor(), newName);
var newNodePath = node.getNodeUri();
var newNodePath = node.getNodeItemPath();
addNavigatorNodeMoveEvent(session, node, oldNodePath, newNodePath);
return node.getName();
}
Expand Down Expand Up @@ -536,7 +536,7 @@ public int deleteNodes(
ne.getValue().deleteObject(commandContext, object, options);
commandContext.saveChanges(session.getProgressMonitor(), options);
} else if (node instanceof DBNLocalFolder) {
var nodePath = node.getNodeUri();
var nodePath = node.getNodeItemPath();
node.getOwnerProject().getDataSourceRegistry().removeFolder(((DBNLocalFolder) node).getFolder(), false);
WebEventUtils.addNavigatorNodeUpdatedEvent(
session.getProjectById(projectId),
Expand Down Expand Up @@ -622,12 +622,12 @@ public boolean moveNodesToFolder(
}
}
DBNLocalFolder dbnLocalFolder = ((DBNLocalFolder) node);
var oldNodePath = node.getNodeUri();
var oldNodePath = node.getNodeItemPath();
node.getOwnerProject().getDataSourceRegistry().moveFolder(
dbnLocalFolder.getFolder().getFolderPath(),
dbnLocalFolder.generateNewFolderPath(parentFolder, dbnLocalFolder.getNodeDisplayName())
);
var newNodePath = node.getNodeUri();
var newNodePath = node.getNodeItemPath();
WebServiceUtils.updateConfigAndRefreshDatabases(session, node.getOwnerProject().getId());
addNavigatorNodeMoveEvent(session, node, oldNodePath, newNodePath);
} else if (node instanceof DBNResourceManagerResource) {
Expand Down
5 changes: 4 additions & 1 deletion webapp/packages/plugin-gis-viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"geojson": "^0.5.0",
"leaflet": "^1.9.4",
"mobx-react-lite": "^4.0.5",
"proj4": "^2.10.0",
"react": "^18.2.0",
"react-leaflet": "^4.2.1",
"reshadow": "^0.0.1",
Expand All @@ -37,7 +38,9 @@
"@types/react": "^18.2.42",
"@types/react-leaflet": "~3.0.0",
"@types/wellknown": "~0.5.8",
"@types/proj4": "^2.5.5",
"leaflet": "^1.9.4",
"typescript": "^5.3.2"
"typescript": "^5.3.2",
"typescript-plugin-css-modules": "^5.0.2"
}
}
10 changes: 10 additions & 0 deletions webapp/packages/plugin-gis-viewer/src/CrsInput.m.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.root {
display: inline-flex;
align-items: center;
font-size: 12px;
}

.combobox {
width: 120px;
flex: 0 0 auto;
}
40 changes: 13 additions & 27 deletions webapp/packages/plugin-gis-viewer/src/CrsInput.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,26 @@
import styled, { css } from 'reshadow';

/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { Combobox } from '@cloudbeaver/core-blocks';

import classes from './CrsInput.m.css';
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'];
const items: CrsKey[] = ['Simple', 'EPSG:3395', 'EPSG:3857', 'EPSG:4326', 'EPSG:900913'];

export function CrsInput(props: Props) {
return styled(styles)(
<root>
<label>CRS:</label>
<Combobox items={items} value={props.value} onSelect={props.onChange} />
</root>,
return (
<div className={classes.root}>
<Combobox className={classes.combobox} items={items} value={props.value} onSelect={props.onChange} />
</div>
);
}
16 changes: 16 additions & 0 deletions webapp/packages/plugin-gis-viewer/src/GISValuePresentation.m.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.root {
display: flex;
flex-direction: column;
width: 100%;
}

.map {
flex: 1 1 auto;
border-radius: var(--theme-group-element-radius);
overflow: hidden;
}

.toolbar {
margin-top: 8px;
flex: 0 0 auto;
}
104 changes: 65 additions & 39 deletions webapp/packages/plugin-gis-viewer/src/GISValuePresentation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
* you may not use this file except in compliance with the License.
*/
import { observer } from 'mobx-react-lite';
import { useCallback, useMemo, useState } from 'react';
import styled, { css } from 'reshadow';
import wellknown from 'wellknown';
import proj4 from 'proj4';
import { useCallback, useState } from 'react';
import wellknown, { GeoJSONGeometry } from 'wellknown';

import { TextPlaceholder, useTranslate } from '@cloudbeaver/core-blocks';
import {
Expand All @@ -21,42 +21,56 @@ import {
} from '@cloudbeaver/plugin-data-viewer';

import { CrsInput } from './CrsInput';
import classes from './GISValuePresentation.m.css';
import { CrsKey, IAssociatedValue, IGeoJSONFeature, LeafletMap } from './LeafletMap';
import { ResultSetGISAction } from './ResultSetGISAction';

function getCrsKey(feature?: IGeoJSONFeature): CrsKey {
switch (feature?.properties.srid) {
proj4.defs('EPSG:3395', '+title=World Mercator +proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs');

function getCrsKey(srid: number): CrsKey {
switch (srid) {
case 3857:
return 'EPSG3857';
return 'EPSG:3857';
case 4326:
return 'EPSG4326';
return 'EPSG:4326';
case 3395:
return 'EPSG3395';
return 'EPSG:3395';
case 900913:
return 'EPSG900913';
return 'EPSG:900913';
default:
return 'EPSG3857';
return 'EPSG:4326';
}
}

const styles = css`
root {
display: flex;
flex-direction: column;
width: 100%;
const DEFAULT_CRS = 'EPSG:3857';
const DEFAULT_TRANSFORM_CRS = 'EPSG:4326';

function getTransformedGeometry(from: CrsKey, to: CrsKey, geometry: GeoJSONGeometry): GeoJSONGeometry {
if (geometry.type === 'Point') {
return { ...geometry, coordinates: proj4(from, to, geometry.coordinates) };
}

if (geometry.type === 'MultiPoint' || geometry.type === 'LineString') {
return { ...geometry, coordinates: geometry.coordinates.map(point => proj4(from, to, point)) };
}

map {
flex: 1 1 auto;
border-radius: var(--theme-group-element-radius);
overflow: hidden;
if (geometry.type === 'MultiLineString' || geometry.type === 'Polygon') {
return { ...geometry, coordinates: geometry.coordinates.map(line => line.map(point => proj4(from, to, point))) };
}

toolbar {
margin-top: 8px;
flex: 0 0 auto;
if (geometry.type === 'MultiPolygon') {
return {
...geometry,
coordinates: geometry.coordinates.map(polygon => polygon.map(line => line.map(point => proj4(from, to, point)))),
};
}
`;

if (geometry.type === 'GeometryCollection') {
return { ...geometry, geometries: geometry.geometries.map(geometry => getTransformedGeometry(from, to, geometry)) };
}

return geometry;
}

interface Props {
model: IDatabaseDataModel<any, IDatabaseResultSet>;
Expand All @@ -70,9 +84,15 @@ export const GISValuePresentation = observer<Props>(function GISValuePresentatio
const gis = model.source.getAction(resultIndex, ResultSetGISAction);
const view = model.source.getAction(resultIndex, ResultSetViewAction);

const parsedGISData: IGeoJSONFeature[] = [];
const activeElements = selection.getActiveElements();
const firstActiveElement = activeElements[0];
const firstActiveCell = firstActiveElement ? gis.getCellValue(firstActiveElement) : null;
const initialCrs: CrsKey = firstActiveCell?.srid ? getCrsKey(firstActiveCell.srid) : DEFAULT_CRS;

const parsedGISData: IGeoJSONFeature[] = [];
const [crs, setCrs] = useState<CrsKey | null>(null);

const currentCrs = crs ?? initialCrs;

for (const cell of activeElements) {
const cellValue = gis.getCellValue(cell);
Expand All @@ -81,15 +101,24 @@ export const GISValuePresentation = observer<Props>(function GISValuePresentatio
continue;
}

const text = cellValue.mapText || cellValue.text;

try {
const parsedCellValue = wellknown.parse(cellValue.mapText || cellValue.text);
const parsedCellValue = wellknown.parse(text);

if (!parsedCellValue) {
continue;
}

parsedGISData.push({ type: 'Feature', geometry: parsedCellValue, properties: { associatedCell: cell, srid: cellValue.srid } });
const from = cellValue.srid === 0 ? DEFAULT_TRANSFORM_CRS : getCrsKey(cellValue.srid);

parsedGISData.push({
type: 'Feature',
geometry: currentCrs === 'Simple' ? parsedCellValue : getTransformedGeometry(from, currentCrs, parsedCellValue),
properties: { associatedCell: cell, srid: cellValue.srid },
});
} catch (exception: any) {
console.error(`Failed to parse "${cellValue.mapText || cellValue.text}" value.`);
console.error(`Failed to parse "${text}" value.`);
console.error(exception);
}
}
Expand Down Expand Up @@ -119,21 +148,18 @@ export const GISValuePresentation = observer<Props>(function GISValuePresentatio
[view],
);

const defaultCrsKey = getCrsKey(parsedGISData[0]);
const [crsKey, setCrsKey] = useState(defaultCrsKey);

if (!parsedGISData.length) {
return <TextPlaceholder>{translate('gis_presentation_placeholder')}</TextPlaceholder>;
}

return styled(styles)(
<root>
<map>
<LeafletMap key={crsKey} geoJSON={parsedGISData} crsKey={crsKey} getAssociatedValues={getAssociatedValues} />
</map>
<toolbar>
<CrsInput value={crsKey} onChange={setCrsKey} />
</toolbar>
</root>,
return (
<div className={classes.root}>
<div className={classes.map}>
<LeafletMap key={currentCrs} geoJSON={parsedGISData} crsKey={currentCrs} getAssociatedValues={getAssociatedValues} />
</div>
<div className={classes.toolbar}>
<CrsInput value={currentCrs} onChange={setCrs} />
</div>
</div>
);
});
23 changes: 8 additions & 15 deletions webapp/packages/plugin-gis-viewer/src/LeafletMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
import type geojson from 'geojson';
import leaflet from 'leaflet';
import { useCallback, useEffect, useState } from 'react';
import { GeoJSON, LayersControl, MapContainer, TileLayer } from 'react-leaflet';
import type { TileLayerProps } from 'react-leaflet';
import { GeoJSON, LayersControl, MapContainer, TileLayer, type TileLayerProps } from 'react-leaflet';
import styled, { css } from 'reshadow';

import { useSplit, useTranslate } from '@cloudbeaver/core-blocks';
Expand Down Expand Up @@ -39,7 +38,7 @@ interface IBaseTile extends TileLayerProps {
checked?: boolean;
}

export type CrsKey = 'Simple' | 'EPSG3857' | 'EPSG4326' | 'EPSG3395' | 'EPSG900913';
export type CrsKey = 'Simple' | 'EPSG:3857' | 'EPSG:4326' | 'EPSG:3395' | 'EPSG:900913';

interface Props {
geoJSON: IGeoJSONFeature[];
Expand Down Expand Up @@ -92,13 +91,13 @@ function getCRS(crsKey: CrsKey): leaflet.CRS {
switch (crsKey) {
case 'Simple':
return leaflet.CRS.Simple;
case 'EPSG3857':
case 'EPSG:3857':
return leaflet.CRS.EPSG3857;
case 'EPSG4326':
case 'EPSG:4326':
return leaflet.CRS.EPSG4326;
case 'EPSG3395':
case 'EPSG:3395':
return leaflet.CRS.EPSG3395;
case 'EPSG900913':
case 'EPSG:900913':
return leaflet.CRS.EPSG900913;
default:
return leaflet.CRS.EPSG3857;
Expand Down Expand Up @@ -175,20 +174,14 @@ export const LeafletMap: React.FC<Props> = function LeafletMap({ geoJSON, crsKey
useEffect(() => {
if (mapRef) {
mapRef.invalidateSize();

if (mapRef.options.crs?.code !== crs.code) {
const center = mapRef.getCenter();
mapRef.options.crs = crs;
mapRef.setView(center);
}
}
}, [split.state.isResizing, split.state.mode, crs, mapRef]);
}, [split.state.isResizing, split.state.mode, mapRef]);

return styled(
styles,
baseStyles,
)(
<MapContainer ref={setMapRef} crs={crs} zoom={12}>
<MapContainer ref={setMapRef} crs={leaflet.CRS.EPSG3857} zoom={12}>
<GeoJSON
// data is not optional property, see react-leaflet.d.ts
// data={[]}
Expand Down
Loading

0 comments on commit b663564

Please sign in to comment.