map - show geometry in MySQL

This commit is contained in:
Jan Prochazka
2022-06-11 09:45:23 +02:00
parent 0a0ce6ad98
commit 343cf84a58
9 changed files with 248 additions and 14 deletions

View File

@@ -483,6 +483,22 @@ export abstract class GridDisplay {
processReferences(select: Select, displayedColumnInfo: DisplayedColumnInfo, options) {}
createColumnExpression(col, source, alias?) {
let expr = null;
if (this.dialect.createColumnViewExpression) {
expr = this.dialect.createColumnViewExpression(col.columnName, col.dataType, source, alias);
if (expr) {
return expr;
}
}
return {
exprType: 'column',
alias: alias || col.columnName,
source,
...col,
};
}
createSelectBase(name: NamedObjectInfo, columns: ColumnInfo[], options) {
if (!columns) return null;
const orderColumnName = columns[0].columnName;
@@ -492,12 +508,7 @@ export abstract class GridDisplay {
name: _.pick(name, ['schemaName', 'pureName']),
alias: 'basetbl',
},
columns: columns.map(col => ({
exprType: 'column',
alias: col.columnName,
source: { alias: 'basetbl' },
...col,
})),
columns: columns.map(col => this.createColumnExpression(col, { alias: 'basetbl' })),
orderBy: [
{
exprType: 'column',

View File

@@ -267,12 +267,9 @@ export class TableGridDisplay extends GridDisplay {
) {
for (const column of columns) {
if (this.addAllExpandedColumnsToSelected || this.config.addedColumns.includes(column.uniqueName)) {
select.columns.push({
exprType: 'column',
columnName: column.columnName,
alias: column.uniqueName,
source: { name: column, alias: parentAlias },
});
select.columns.push(
this.createColumnExpression(column, { name: column, alias: parentAlias }, column.uniqueName)
);
displayedColumnInfo[column.uniqueName] = {
...column,
sourceAlias: parentAlias,

View File

@@ -84,3 +84,18 @@ export function getIconForRedisType(type) {
return null;
}
}
export function isWktGeometry(s) {
if (!_isString(s)) return false;
return (
s.startsWith('POINT(') ||
s.startsWith('LINESTRING(') ||
s.startsWith('POLYGON(') ||
s.startsWith('MULTIPOINT(') ||
s.startsWith('MULTILINESTRING(') ||
s.startsWith('MULTIPOLYGON(') ||
s.startsWith('GEOMCOLLECTION(') ||
s.startsWith('GEOMETRYCOLLECTION(')
);
}

View File

@@ -34,4 +34,7 @@ export interface SqlDialect {
disableExplicitTransaction?: boolean;
predefinedDataTypes: string[];
// create sql-tree expression
createColumnViewExpression(columnName: string, dataType: string, source: { alias: string }, alias?: string): any;
}

View File

@@ -57,6 +57,8 @@
"dependencies": {
"chartjs-plugin-zoom": "^1.2.0",
"date-fns": "^2.28.0",
"interval-operations": "^1.0.7"
"interval-operations": "^1.0.7",
"leaflet": "^1.8.0",
"wellknown": "^0.5.0"
}
}

View File

@@ -0,0 +1,111 @@
<script lang="ts">
import _ from 'lodash';
import { onMount } from 'svelte';
import 'leaflet/dist/leaflet.css';
import leaflet from 'leaflet';
import wellknown from 'wellknown';
import { isWktGeometry } from 'dbgate-tools';
// import Map from 'ol/Map';
// import View from 'ol/View';
// import TileLayer from 'ol/layer/Tile';
// import XYZ from 'ol/source/XYZ';
export let selection;
export let wrap;
let refContainer;
let map;
let selectionLayers = [];
function addSelectionToMap() {
if (!map) return;
if (!selection) return;
for (const selectionLayer of selectionLayers) {
selectionLayer.remove();
}
selectionLayers = [];
const geoValues = selection.map(x => x.value).filter(isWktGeometry);
if (geoValues.length > 0) {
// parse WKT to geoJSON array
const geometries = geoValues.map(wellknown);
const geoJson = {
type: 'GeometryCollection',
geometries,
};
const geoJsonObj = leaflet
.geoJSON(geoJson, {
style: function () {
return {
weight: 2,
fillColor: '#ff7800',
color: '#ff7800',
opacity: 0.8,
fillOpacity: 0.4,
};
},
pointToLayer: function (feature, latlng) {
return leaflet.circleMarker(latlng, {
radius: 7,
weight: 2,
fillColor: '#ff7800',
color: '#ff7800',
opacity: 0.8,
fillOpacity: 0.4,
});
},
})
.addTo(map);
map.fitBounds(geoJsonObj.getBounds());
selectionLayers.push(geoJsonObj);
}
}
onMount(() => {
// new Map({
// target: refContainer,
// layers: [
// new TileLayer({
// source: new XYZ({
// url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png',
// }),
// }),
// ],
// view: new View({
// center: [0, 0],
// zoom: 2,
// }),
// });
map = leaflet.map(refContainer); // .setView([51.505, -0.09], 13);
leaflet
.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap',
})
.addTo(map);
addSelectionToMap();
// map.fitBounds([
// [50, 15],
// [50.1, 15],
// [50, 15.1],
// ]);
// const marker = leaflet.marker([50, 15]).addTo(map);
// <div bind:this={refContainer} class="flex1 map-container" />
});
$: {
selection;
addSelectionToMap();
}
</script>
<div bind:this={refContainer} class="flex1" />

View File

@@ -1,4 +1,6 @@
<script lang="ts" context="module">
import { isWktGeometry } from 'dbgate-tools';
const formats = [
{
type: 'textWrap',
@@ -36,12 +38,31 @@
component: HtmlCellView,
single: false,
},
{
type: 'map',
title: 'Map',
component: MapCellView,
single: false,
},
];
function autodetect(selection) {
if (selection[0]?.engine?.databaseEngineTypes?.includes('document')) {
return 'jsonRow';
}
if (selection.length > 0 && _.every(selection, x => isWktGeometry(x.value))) {
return 'map';
}
if (
selection.find(x => x.column.toLowerCase().includes('lat')) &&
(selection.find(x => x.column.toLowerCase().includes('lon')) ||
selection.find(x => x.column.toLowerCase().includes('lng')))
) {
return 'map';
}
const value = selection.length == 1 ? selection[0].value : null;
if (_.isString(value)) {
if (value.startsWith('[') || value.startsWith('{')) return 'json';
@@ -62,6 +83,7 @@
import HtmlCellView from '../celldata/HtmlCellView.svelte';
import JsonCellView from '../celldata/JsonCellView.svelte';
import JsonRowView from '../celldata/JsonRowView.svelte';
import MapCellView from '../celldata/MapCellView.svelte';
import PictureCellView from '../celldata/PictureCellView.svelte';
import TextCellViewNoWrap from '../celldata/TextCellViewNoWrap.svelte';
import TextCellViewWrap from '../celldata/TextCellViewWrap.svelte';