diff --git a/app/helpers/gtt_map_helper.rb b/app/helpers/gtt_map_helper.rb index fa58a91b..22e22262 100644 --- a/app/helpers/gtt_map_helper.rb +++ b/app/helpers/gtt_map_helper.rb @@ -33,6 +33,7 @@ def map_tag(map: nil, layers: map&.layers, data[:upload] = upload data[:collapsed] = collapsed if collapsed data[:geocoding] = true if Setting.plugin_redmine_gtt['enable_geocoding_on_map'] == 'true' + data[:measure] = true if Setting.plugin_redmine_gtt['default_measure_enabled'] == 'true' data[:target] = true if Setting.plugin_redmine_gtt['default_target_enabled'] == 'true' uid = "ol-" + rand(36**8).to_s(36) diff --git a/app/views/settings/gtt/_general.html.erb b/app/views/settings/gtt/_general.html.erb index 540f4fd8..0a07239f 100644 --- a/app/views/settings/gtt/_general.html.erb +++ b/app/views/settings/gtt/_general.html.erb @@ -72,6 +72,11 @@ <%= check_box_tag 'settings[default_target_enabled]', true, @settings[:default_target_enabled] %>
++ <%= content_tag(:label, l(:label_default_measure_enabled)) %> + <%= check_box_tag 'settings[default_measure_enabled]', true, @settings[:default_measure_enabled] %> +
+
<%= content_tag(:label, l(:label_hide_map_for_invalid_geom)) %>
<%= check_box_tag 'settings[hide_map_for_invalid_geom]', 1, Setting.plugin_redmine_gtt['hide_map_for_invalid_geom'] %>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 3c017577..ae97bef4 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -56,6 +56,7 @@ en:
label_enable_geojson_upload_on_issue_map: "Enable GeoJSON upload on issue map"
label_enable_geocoding_on_map: "Enable geocoding on map"
label_default_target_enabled: "Show target on map center"
+ label_default_measure_enabled: "Show measure control"
select_other_gtt_settings: "Other GTT settings"
label_hide_map_for_invalid_geom: "Hide issue map for invalid geometry"
diff --git a/init.rb b/init.rb
index 75beb000..d9052f7e 100644
--- a/init.rb
+++ b/init.rb
@@ -31,6 +31,7 @@
'default_map_fit_maxzoom_level' => 17,
'vector_minzoom_level' => 0,
'default_target_enabled' => false,
+ 'default_measure_enabled' => false,
'default_geocoder_options' => '{}',
'editable_geometry_types_on_issue_map' => ["Point"],
'enable_geojson_upload_on_issue_map' => false,
diff --git a/src/components/gtt-client/helpers/index.ts b/src/components/gtt-client/helpers/index.ts
index 045a7670..bfee4488 100644
--- a/src/components/gtt-client/helpers/index.ts
+++ b/src/components/gtt-client/helpers/index.ts
@@ -274,3 +274,30 @@ export function parseHistory() {
});
}
+/**
+ * Format length in meters or kilometers.
+ * @param length
+ * @returns
+ */
+export function formatLength(length: number): string {
+ if (length < 1000) {
+ return length.toFixed(0) + ' m';
+ } else {
+ return (length / 1000).toFixed(2) + ' km';
+ }
+}
+
+/**
+ * Format area in square meters or square kilometers.
+ * @param area
+ * @returns
+ */
+export function formatArea(area: number): string {
+ if (area < 10000) {
+ return area.toFixed(1) + ' m2';
+ } else {
+ return (area / 1000000).toFixed(2) + ' km2';
+ }
+}
+
+
diff --git a/src/components/gtt-client/init/controls.ts b/src/components/gtt-client/init/controls.ts
index 6aa7e247..ce2ecac1 100644
--- a/src/components/gtt-client/init/controls.ts
+++ b/src/components/gtt-client/init/controls.ts
@@ -5,10 +5,11 @@ import Button from 'ol-ext/control/Button';
import LayerPopup from 'ol-ext/control/LayerPopup';
import LayerSwitcher from 'ol-ext/control/LayerSwitcher';
import Target from 'ol-ext/control/Target';
+import Hover from 'ol-ext/interaction/Hover';
import Notification from 'ol-ext/control/Notification';
import { position } from 'ol-ext/control/control';
-import { radiansToDegrees, degreesToRadians, parseHistory } from "../helpers";
+import { radiansToDegrees, degreesToRadians, parseHistory, formatLength, formatArea } from "../helpers";
import { zoomToExtent, setGeolocation, setView, setControls, setPopover } from "../openlayers";
import { createSearchControl } from '../geocoding/SearchFactory';
@@ -110,6 +111,35 @@ function addMaximizeControl(instance: any): void {
instance.toolbar.addControl(maximizeCtrl);
}
+/**
+ * Adds hover control to provide additional information
+ * @param instance
+ */
+function addHoverControl(instance: any): void {
+ const hover = new Hover({
+ cursor: 'pointer',
+ handleEvent: (evt: any) => {
+ return true;
+ },
+ layerFilter: (layer: any) => {
+ // Respond only to the specific vector layer
+ return layer === instance.vector;
+ }
+ });
+
+ instance.map.addInteraction(hover);
+
+ // Show the length or area of the feature on hover
+ hover.on('enter', (evt: any) => {
+ const geometry = evt.feature.getGeometry();
+ if (geometry.getType() === 'LineString') {
+ instance.map.notification.show(formatLength(geometry.getLength()));
+ } else if (geometry.getType() === 'Polygon') {
+ instance.map.notification.show(formatArea(geometry.getArea()));
+ }
+ });
+}
+
/**
* Handles the map rotation functionality.
* @param {any} instance - The GttClient instance.
@@ -199,6 +229,10 @@ export function initControls(this: any): void {
handleMapRotation(this);
addTargetControl(this);
+ if (this.contents.measure) {
+ addHoverControl(this);
+ }
+
if (this.contents.edit) {
setControls.call(this, this.contents.edit.split(' '));
} else if (this.contents.popup) {
diff --git a/src/components/gtt-client/openlayers/index.ts b/src/components/gtt-client/openlayers/index.ts
index 1695167e..e57f04a1 100644
--- a/src/components/gtt-client/openlayers/index.ts
+++ b/src/components/gtt-client/openlayers/index.ts
@@ -11,10 +11,16 @@ import Bar from 'ol-ext/control/Bar';
import Button from 'ol-ext/control/Button';
import Toggle from 'ol-ext/control/Toggle';
import Popup from 'ol-ext/overlay/Popup';
+import Tooltip from 'ol-ext/overlay/Tooltip'
import { position } from 'ol-ext/control/control';
import { GeoJSON } from 'ol/format';
-import { getCookie, getMapSize, degreesToRadians, updateForm } from "../helpers";
+import { getCookie, getMapSize, degreesToRadians, updateForm, formatLength, formatArea } from "../helpers";
+
+// Define the types for the Tooltip and the custom methods you added
+interface ExtendedTooltip extends Tooltip {
+ prevHTML?: string;
+}
/**
* Get the z-value for a given geometry.
@@ -133,6 +139,18 @@ function setZValueForGeometry(feature: any, zValue: number): any {
return feature;
}
+/**
+ * Create extended tooltip control
+ * @returns
+ */
+function createTooltip(): ExtendedTooltip {
+ return new Tooltip({
+ maximumFractionDigits: 2,
+ formatLength,
+ formatArea
+ }) as ExtendedTooltip;
+}
+
/**
* Add editing tools
*/
@@ -165,6 +183,11 @@ export function setControls(types: Array