diff --git a/bin/internal/check-release-excludes.sh b/bin/internal/check-release-excludes.sh index 1309291991..e819583a50 100755 --- a/bin/internal/check-release-excludes.sh +++ b/bin/internal/check-release-excludes.sh @@ -58,7 +58,7 @@ validateExtension() { fi ;; resources/js/*) - if [ "${extension}" != "ts" ] && [ "${extension}" != "mjs" ]; then + if [ "${extension}" != "ts" ]; then foundFileExt fi ;; diff --git a/resources/js/gis_data_editor.ts b/resources/js/gis_data_editor.ts index 17a9b68c55..fd5c041c5e 100644 --- a/resources/js/gis_data_editor.ts +++ b/resources/js/gis_data_editor.ts @@ -252,16 +252,12 @@ function makeGeometryInputs (gisData): string { * @param {function} resolve */ function loadJSAndGISEditor (resolve) { - let script; - - script = document.createElement('script'); - script.src = 'js/table/gis_visualization.js'; - document.head.appendChild(script); + let script: HTMLScriptElement; // OpenLayers.js is BIG and takes time. So asynchronous loading would not work. // Load the JS and do a callback to load the content for the GIS Editor. script = document.createElement('script'); - script.src = 'js/vendor/openlayers/OpenLayers.js'; + script.src = 'js/vendor/openlayers/openlayers.js'; script.addEventListener('load', function () { resolve(); }); @@ -272,6 +268,10 @@ function loadJSAndGISEditor (resolve) { document.head.appendChild(script); + script = document.createElement('script'); + script.src = 'js/table/gis_visualization.js'; + document.head.appendChild(script); + gisEditorLoaded = true; } diff --git a/resources/js/global.d.ts b/resources/js/global.d.ts index 967f883969..e3d5f73324 100644 --- a/resources/js/global.d.ts +++ b/resources/js/global.d.ts @@ -4,7 +4,6 @@ interface Window { mysqlDocTemplate: string; themeImagePath: string; firstDayOfCalendar: string; - ol: any; opera: any; zxcvbnts: any; msCrypto: any; diff --git a/resources/js/ol.mjs b/resources/js/ol.mjs deleted file mode 100644 index 620f4da4d6..0000000000 --- a/resources/js/ol.mjs +++ /dev/null @@ -1,36 +0,0 @@ -import { Attribution, MousePosition, Zoom } from 'ol/control.js'; -import { createStringXY } from 'ol/coordinate.js'; -import { isEmpty } from 'ol/extent.js'; -import { LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon } from 'ol/geom.js'; -import { Tile, Vector as VectorLayer } from 'ol/layer.js'; -import { OSM, Vector as VectorSource } from 'ol/source.js'; -import { Circle, Fill, Stroke, Style, Text } from 'ol/style.js'; -import { Feature, Map, View } from 'ol'; -import { get as getProjection } from 'ol/proj.js'; - -const ol = { - control: { - Attribution, MousePosition, Zoom - }, - coordinate: { - createStringXY - }, - extent: { - isEmpty - }, - geom: { - LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon - }, - layer: { - Tile, Vector: VectorLayer - }, - source: { - OSM, Vector: VectorSource - }, - style: { - Circle, Fill, Stroke, Style, Text - }, - Feature, Map, View, getProjection -}; - -export default ol; diff --git a/resources/js/table/gis_visualization.ts b/resources/js/table/gis_visualization.ts index 54405f92ad..fd70631bfa 100644 --- a/resources/js/table/gis_visualization.ts +++ b/resources/js/table/gis_visualization.ts @@ -1,6 +1,15 @@ import $ from 'jquery'; import { AJAX } from '../modules/ajax.ts'; import { escapeHtml } from '../modules/functions/escape.ts'; +import { Feature, Map, View } from 'ol'; +import { Attribution, MousePosition, Zoom } from 'ol/control'; +import { createStringXY } from 'ol/coordinate'; +import { isEmpty } from 'ol/extent'; +import { LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon } from 'ol/geom'; +import { Tile, Vector as VectorLayer } from 'ol/layer'; +import { get as getProjection } from 'ol/proj'; +import { OSM, Vector as VectorSource } from 'ol/source'; +import { Circle, Fill, Stroke, Style, Text } from 'ol/style'; /** * @fileoverview functions used for visualizing GIS data @@ -428,11 +437,11 @@ class OlVisualization extends GisVisualization { } drawOpenLayers () { - if (typeof window.ol === 'undefined') { + if (! document.querySelector('script[src*="js/vendor/openlayers/openlayers.js"]')) { return undefined; } - const olCss = 'js/vendor/openlayers/theme/ol.css'; + const olCss = 'js/vendor/openlayers/openlayers.css'; if (! document.querySelector('link[rel="stylesheet"][href="' + olCss + '"]')) { const link = document.createElement('link'); link.rel = 'stylesheet'; @@ -441,28 +450,28 @@ class OlVisualization extends GisVisualization { document.head.appendChild(link); } - const vectorSource = new window.ol.source.Vector({ + const vectorSource = new VectorSource({ features: getFeaturesFromOpenLayersData(this.data), }); - const map = new window.ol.Map({ + const map = new Map({ target: this.target, layers: [ - new window.ol.layer.Tile({ source: new window.ol.source.OSM() }), - new window.ol.layer.Vector({ source: vectorSource }), + new Tile({ source: new OSM() }), + new VectorLayer({ source: vectorSource }), ], - view: new window.ol.View({ center: [0, 0], zoom: 4 }), + view: new View({ center: [0, 0], zoom: 4 }), controls: [ - new window.ol.control.MousePosition({ - coordinateFormat: window.ol.coordinate.createStringXY(4), + new MousePosition({ + coordinateFormat: createStringXY(4), projection: 'EPSG:4326' }), - new window.ol.control.Zoom, - new window.ol.control.Attribution + new Zoom, + new Attribution ] }); const extent = vectorSource.getExtent(); - if (! window.ol.extent.isEmpty(extent)) { + if (! isEmpty(extent)) { map.getView().fit(extent, { padding: [20, 20, 20, 20] }); } @@ -502,40 +511,40 @@ function getFeaturesFromOpenLayersData (geometries: any[]): any[] { let olGeometry: any = null; const style: any = {}; if (geometry.geometry.type === 'LineString') { - olGeometry = new window.ol.geom.LineString(geometry.geometry.coordinates); - style.stroke = new window.ol.style.Stroke(geometry.style.stroke); + olGeometry = new LineString(geometry.geometry.coordinates); + style.stroke = new Stroke(geometry.style.stroke); } else if (geometry.geometry.type === 'MultiLineString') { - olGeometry = new window.ol.geom.MultiLineString(geometry.geometry.coordinates); - style.stroke = new window.ol.style.Stroke(geometry.style.stroke); + olGeometry = new MultiLineString(geometry.geometry.coordinates); + style.stroke = new Stroke(geometry.style.stroke); } else if (geometry.geometry.type === 'MultiPoint') { - olGeometry = new window.ol.geom.MultiPoint(geometry.geometry.coordinates); - style.image = new window.ol.style.Circle({ - fill: new window.ol.style.Fill(geometry.style.circle.fill), - stroke: new window.ol.style.Stroke(geometry.style.circle.stroke), + olGeometry = new MultiPoint(geometry.geometry.coordinates); + style.image = new Circle({ + fill: new Fill(geometry.style.circle.fill), + stroke: new Stroke(geometry.style.circle.stroke), radius: geometry.style.circle.radius, }); } else if (geometry.geometry.type === 'MultiPolygon') { - olGeometry = new window.ol.geom.MultiPolygon(geometry.geometry.coordinates); - style.fill = new window.ol.style.Fill(geometry.style.fill); - style.stroke = new window.ol.style.Stroke(geometry.style.stroke); + olGeometry = new MultiPolygon(geometry.geometry.coordinates); + style.fill = new Fill(geometry.style.fill); + style.stroke = new Stroke(geometry.style.stroke); } else if (geometry.geometry.type === 'Point') { - olGeometry = new window.ol.geom.Point(geometry.geometry.coordinates); - style.image = new window.ol.style.Circle({ - fill: new window.ol.style.Fill(geometry.style.circle.fill), - stroke: new window.ol.style.Stroke(geometry.style.circle.stroke), + olGeometry = new Point(geometry.geometry.coordinates); + style.image = new Circle({ + fill: new Fill(geometry.style.circle.fill), + stroke: new Stroke(geometry.style.circle.stroke), radius: geometry.style.circle.radius, }); } else if (geometry.geometry.type === 'Polygon') { - olGeometry = new window.ol.geom.Polygon(geometry.geometry.coordinates); - style.fill = new window.ol.style.Fill(geometry.style.fill); - style.stroke = new window.ol.style.Stroke(geometry.style.stroke); + olGeometry = new Polygon(geometry.geometry.coordinates); + style.fill = new Fill(geometry.style.fill); + style.stroke = new Stroke(geometry.style.stroke); } else { throw new Error(); } if (geometry.geometry.srid !== 3857) { const source = 'EPSG:' + (geometry.geometry.srid !== 0 ? geometry.geometry.srid : 4326); - const sourceProj = window.ol.getProjection(source); + const sourceProj = getProjection(source); if (sourceProj) { olGeometry = olGeometry.transform( @@ -546,11 +555,11 @@ function getFeaturesFromOpenLayersData (geometries: any[]): any[] { } if (geometry.style.text) { - style.text = new window.ol.style.Text(geometry.style.text); + style.text = new Text(geometry.style.text); } - const feature = new window.ol.Feature(olGeometry); - feature.setStyle(new window.ol.style.Style(style)); + const feature = new Feature(olGeometry); + feature.setStyle(new Style(style)); features.push(feature); } @@ -572,7 +581,7 @@ class GisVisualizationController { $(document).on('click', '#useOsmAsBaseLayerSwitch', this.boundOnChoiceChange); - if (typeof window.ol === 'undefined') { + if (! document.querySelector('script[src*="js/vendor/openlayers/openlayers.js"]')) { $('#useOsmAsBaseLayerSwitch, #useOsmAsBaseLayerSwitchLabel').hide(); $('#useOsmAsBaseLayerSwitch').prop('checked', false); } diff --git a/src/Controllers/Table/GisVisualizationController.php b/src/Controllers/Table/GisVisualizationController.php index ecd7b74435..eeb9745d85 100644 --- a/src/Controllers/Table/GisVisualizationController.php +++ b/src/Controllers/Table/GisVisualizationController.php @@ -124,7 +124,7 @@ final readonly class GisVisualizationController implements InvocableController return $response->write((string) $output); } - $this->response->addScriptFiles(['vendor/openlayers/OpenLayers.js', 'table/gis_visualization.js']); + $this->response->addScriptFiles(['vendor/openlayers/openlayers.js', 'table/gis_visualization.js']); // If all the rows contain SRID, use OpenStreetMaps on the initial loading. $useBaseLayer = isset($_POST['redraw']) ? isset($_POST['useBaseLayer']) : $visualization->hasSrid(); diff --git a/webpack.config.cjs b/webpack.config.cjs index 1f35585876..aa0e55ea35 100644 --- a/webpack.config.cjs +++ b/webpack.config.cjs @@ -1,5 +1,4 @@ const path = require('path'); -const webpack = require('webpack'); const autoprefixer = require('autoprefixer'); const CopyPlugin = require('copy-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); @@ -93,6 +92,14 @@ module.exports = [ minChunks: 2, minSize: 1, }, + openLayers: { + priority: 10, + test: /[\\/]node_modules[\\/](ol|rbush)[\\/]/, + name: 'openlayers', + filename: 'vendor/[name]/[name].js', + chunks: 'all', + enforce: true, + }, }, }, }, @@ -150,7 +157,7 @@ module.exports = [ { from: rootPath + '/node_modules/jquery-uitablefilter/jquery.uitablefilter.js', to: publicPath + '/js/vendor/jquery/jquery.uitablefilter.js' }, { from: rootPath + '/node_modules/tablesorter/dist/js/jquery.tablesorter.js', to: publicPath + '/js/vendor/jquery/jquery.tablesorter.js' }, { from: rootPath + '/node_modules/jquery-ui-timepicker-addon/dist/jquery-ui-timepicker-addon.js', to: publicPath + '/js/vendor/jquery/jquery-ui-timepicker-addon.js' }, - { from: rootPath + '/node_modules/ol/ol.css', to: publicPath + '/js/vendor/openlayers/theme/ol.css' }, + { from: rootPath + '/node_modules/ol/ol.css', to: publicPath + '/js/vendor/openlayers/openlayers.css' }, { from: rootPath + '/node_modules/locutus.sprintf/src/php/strings/sprintf.browser.js', to: publicPath + '/js/vendor/sprintf.js' }, { from: rootPath + '/node_modules/chart.js/dist/chart.umd.js', to: publicPath + '/js/vendor/chart.umd.js' }, { from: rootPath + '/node_modules/chart.js/dist/chart.umd.js.map', to: publicPath + '/js/vendor/chart.umd.js.map' }, @@ -161,32 +168,6 @@ module.exports = [ }), ], }, - { - name: 'OpenLayers', - entry: rootPath + '/resources/js/ol.mjs', - devtool: 'source-map', - mode: 'production', - performance: { - hints: false, - maxEntrypointSize: 512000, - maxAssetSize: 512000, - }, - output: { - path: publicPath + '/js/vendor/openlayers', - filename: 'OpenLayers.js', - library: 'ol', - libraryTarget: 'umd', - libraryExport: 'default', - }, - plugins: [ - new webpack.BannerPlugin({ - banner: 'OpenLayers (https://openlayers.org/)\nCopyright 2005-present, OpenLayers Contributors All rights reserved.\nLicensed under BSD 2-Clause License (https://github.com/openlayers/openlayers/blob/main/LICENSE.md)', - }), - ], - optimization: { - minimize: false, - } - }, { name: 'CSS', mode: 'none',