Skip to content

Commit a91d9fb

Browse files
committed
Merge remote-tracking branch 'origin/main' into ftr/update-dependencies
2 parents 370ea10 + 1e2c634 commit a91d9fb

File tree

6 files changed

+100
-20
lines changed

6 files changed

+100
-20
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div id="dialog-geojson-upload" title="<%= l(:title_geojson_upload) %>">
2+
<textarea placeholder="<%= l(:placeholder_geojson_upload) %>" class="ui-widget ui-state-default ui-corner-all"></textarea>
3+
<input type="file" id="file-selector" accept=".json,.geojson">
4+
</div>

config/locales/en.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,21 @@ en:
8686

8787
project_module_gtt: "GTT"
8888
permission_manage_gtt_settings: "Manage GTT settings"
89+
90+
title_geojson_upload: "Import GeoJSON"
91+
placeholder_geojson_upload: "Please paste a GeoJSON geometry here, or import the GeoJSON data from a file."
92+
93+
# Localize for use in Javascript
94+
gtt_js:
95+
control:
96+
geocoding: "Location search"
97+
geolocation: "My location"
98+
maximize: "Zoom to all features"
99+
upload: "Upload GeoJSON"
100+
fullscreen: "Toggle full-screen"
101+
rotate: "Reset rotation"
102+
zoom-in: "Zoom in"
103+
zoom-out: "Zoom out"
104+
modal:
105+
load: "Load"
106+
cancel: "Cancel"

lib/redmine_gtt/hooks/view_layouts_base_html_head_hook.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ def view_layouts_base_body_bottom(context={})
2929
:maxzoom => Setting.plugin_redmine_gtt['default_map_maxzoom_level'],
3030
:fit_maxzoom => Setting.plugin_redmine_gtt['default_map_fit_maxzoom_level'],
3131
:geocoder => geocoder,
32-
:plugin_settings => Setting.plugin_redmine_gtt.select{ |key, value| key.to_s.match(/^(?!default).+/) }
32+
:plugin_settings => Setting.plugin_redmine_gtt.select{ |key, value| key.to_s.match(/^(?!default).+/) },
33+
:i18n => l(:gtt_js).to_json.html_safe
3334
}, :id => 'gtt-defaults', :style => 'display:none')
3435
return tags.join("\n")
3536
end

lib/redmine_gtt/view_hooks.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,9 @@ class ViewHooks < Redmine::Hook::ViewListener
1313

1414
render_on :view_issues_form_details_top,
1515
partial: 'redmine_gtt/hooks/view_issues_form_details_top'
16+
17+
render_on :view_layouts_base_body_bottom,
18+
partial: 'redmine_gtt/hooks/view_layouts_base_body_bottom'
19+
1620
end
1721
end

src/components/gtt-client.ts

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export class GttClient {
7878
layerArray: Layer[]
7979
defaults: DOMStringMap
8080
contents: DOMStringMap
81+
i18n: any
8182
toolbar: Bar
8283
filters: FilterOption
8384
vector: VectorLayer<VectorSource<Geometry>>
@@ -123,8 +124,8 @@ export class GttClient {
123124
this.defaults.geocoder = JSON.stringify(quick_hack.geocoder)
124125
}
125126

126-
127127
this.contents = options.target.dataset
128+
this.i18n = JSON.parse(this.defaults.i18n)
128129

129130
// create map at first
130131
this.map = new Map({
@@ -290,8 +291,6 @@ export class GttClient {
290291
})
291292
}
292293

293-
294-
295294
// For map div focus settings
296295
if (options.target) {
297296
if (options.target.getAttribute('tabindex') == null) {
@@ -313,13 +312,17 @@ export class GttClient {
313312
this.setGeolocation(this.map)
314313
this.parseHistory()
315314

316-
this.map.addControl (new FullScreen())
317-
this.map.addControl (new Rotate())
315+
this.map.addControl (new FullScreen({
316+
tipLabel: this.i18n.control.fullscreen
317+
}))
318+
this.map.addControl (new Rotate({
319+
tipLabel: this.i18n.control.rotate
320+
}))
318321

319322
// Control button
320323
const maximizeCtrl = new Button({
321324
html: '<i class="material-icons" >zoom_out_map</i>',
322-
title: "Maximize",
325+
title: this.i18n.control.maximize,
323326
handleClick: () => {
324327
this.zoomToExtent(true);
325328
}
@@ -489,24 +492,61 @@ export class GttClient {
489492
editbar.addControl(control)
490493
})
491494

492-
// Upload button
493-
if (this.contents.upload === "true") {
494-
editbar.addControl(new Button({
495-
html: '<i class="material-icons">file_upload</i>',
496-
title: 'Upload GeoJSON',
497-
handleClick: () => {
498-
const data = prompt("Please paste a GeoJSON geometry here")
495+
// Uses jQuery UI for GeoJSON Upload modal window
496+
const mapObj = this
497+
const dialog = $("#dialog-geojson-upload").dialog({
498+
autoOpen: false,
499+
resizable: true,
500+
height: 'auto',
501+
width: 380,
502+
modal: true,
503+
buttons: {
504+
[mapObj.i18n.modal.load]: function() {
505+
const geojson_input = document.querySelector('#dialog-geojson-upload textarea') as HTMLInputElement
506+
const data = geojson_input.value
499507
if (data !== null) {
500508
const features = new GeoJSON().readFeatures(
501509
JSON.parse(data), {
502510
featureProjection: 'EPSG:3857'
503511
}
504512
)
505-
this.vector.getSource().clear()
506-
this.vector.getSource().addFeatures(features)
507-
this.updateForm(features)
508-
this.zoomToExtent()
513+
mapObj.vector.getSource().clear()
514+
mapObj.vector.getSource().addFeatures(features)
515+
mapObj.updateForm(features)
516+
mapObj.zoomToExtent()
509517
}
518+
$(this).dialog('close')
519+
},
520+
[mapObj.i18n.modal.cancel]: function() {
521+
$(this).dialog('close')
522+
}
523+
}
524+
});
525+
526+
// Upload button
527+
if (this.contents.upload === "true") {
528+
529+
const fileSelector = document.getElementById('file-selector')
530+
fileSelector.addEventListener('change', (event: any) => {
531+
const file = event.target.files[0]
532+
// Check if the file is GeoJSON.
533+
if (file.type && !file.type.startsWith('application/geo')) {
534+
console.log('File is not a GeoJSON document.', file.type, file);
535+
return;
536+
}
537+
const fileReader = new FileReader();
538+
fileReader.addEventListener('load', (event: any) => {
539+
const geojson_input = document.querySelector('#dialog-geojson-upload textarea') as HTMLInputElement
540+
geojson_input.value = JSON.stringify(event.target.result, null, 2)
541+
});
542+
fileReader.readAsText(file);
543+
});
544+
545+
editbar.addControl(new Button({
546+
html: '<i class="material-icons">file_upload</i>',
547+
title: this.i18n.control.geojson,
548+
handleClick: () => {
549+
dialog.dialog('open')
510550
}
511551
}))
512552
}
@@ -978,7 +1018,7 @@ export class GttClient {
9781018
// Control button
9791019
const geolocationCtrl = new Toggle({
9801020
html: '<i class="material-icons">my_location</i>',
981-
title: "Geolocation",
1021+
title: this.i18n.control.geolocation,
9821022
active: false,
9831023
onToggle: (active: boolean) => {
9841024
geolocation.setTracking(active)
@@ -1167,7 +1207,7 @@ export class GttClient {
11671207
// Control button
11681208
const geocodingCtrl = new Toggle({
11691209
html: '<i class="material-icons">manage_search</i>',
1170-
title: "Geocoding",
1210+
title: this.i18n.control.geocoding,
11711211
className: "ctl-geocoding",
11721212
onToggle: (active: boolean) => {
11731213
const text = (document.querySelector("div#" + mapId + " .ctl-geocoding div input") as HTMLInputElement)

src/stylesheets/app.scss

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,16 @@ i[id^='icon_settings_tracker_'] {
106106
max-width: 510px;
107107
padding: 0.5em;
108108
}
109+
110+
.ui-dialog .ui-dialog-buttonpane button {
111+
height: inherit;
112+
}
113+
114+
.ui-dialog .ui-dialog-content {
115+
padding: 0.5em 0 0 0;
116+
}
117+
118+
.ui-dialog .ui-dialog-content textarea {
119+
width: 100%;
120+
height: 300px;
121+
}

0 commit comments

Comments
 (0)