From: Tom Hughes Date: Wed, 1 Jan 2025 13:34:16 +0000 (+0000) Subject: Merge remote-tracking branch 'upstream/pull/5451' X-Git-Tag: live~457 X-Git-Url: https://git.openstreetmap.org./rails.git/commitdiff_plain/d38f6484e1aa201284b7eac19dbcc7fad856b88a?hp=91ea18ef7ab6e8cd8bbba6e1528af52fe7ca9aab Merge remote-tracking branch 'upstream/pull/5451' --- diff --git a/Gemfile.lock b/Gemfile.lock index ab8d9f9d1..02b177790 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -92,8 +92,8 @@ GEM autoprefixer-rails (10.4.19.0) execjs (~> 2) aws-eventstream (1.3.0) - aws-partitions (1.1026.0) - aws-sdk-core (3.214.0) + aws-partitions (1.1029.0) + aws-sdk-core (3.214.1) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) @@ -120,7 +120,7 @@ GEM erubi (~> 1.4) parser (>= 2.4) smart_properties - bigdecimal (3.1.8) + bigdecimal (3.1.9) binding_of_caller (1.0.1) debug_inspector (>= 1.2.0) bootsnap (1.18.4) @@ -131,7 +131,7 @@ GEM bootstrap_form (5.4.0) actionpack (>= 6.1) activemodel (>= 6.1) - brakeman (6.2.2) + brakeman (7.0.0) racc brotli (0.6.0) browser (5.3.1) @@ -273,7 +273,7 @@ GEM faraday (>= 0.8) faraday-net_http (3.4.0) net-http (>= 0.5.0) - ffi (1.17.0) + ffi (1.17.1) ffi-compiler (1.3.2) ffi (>= 1.15.5) rake @@ -340,7 +340,7 @@ GEM railties (>= 4.2.0) thor (>= 0.14, < 2.0) json (2.9.1) - jwt (2.9.3) + jwt (2.10.1) base64 kgio (2.11.4) kramdown (2.5.1) @@ -383,7 +383,7 @@ GEM nap (1.1.0) net-http (0.6.0) uri - net-imap (0.5.2) + net-imap (0.5.4) date net-protocol net-pop (0.1.2) @@ -393,7 +393,7 @@ GEM net-smtp (0.5.0) net-protocol nio4r (2.7.4) - nokogiri (1.17.2) + nokogiri (1.18.1) mini_portile2 (~> 2.8.2) racc (~> 1.4) oauth (1.1.0) @@ -481,7 +481,7 @@ GEM rack (~> 2.2, >= 2.2.4) rack-session (1.0.2) rack (< 3) - rack-test (2.1.0) + rack-test (2.2.0) rack (>= 1.3) rack-uri_sanitizer (0.0.2) rackup (1.0.1) @@ -534,7 +534,7 @@ GEM rchardet (1.8.0) rdoc (6.10.0) psych (>= 4.0.0) - regexp_parser (2.9.3) + regexp_parser (2.10.0) reline (0.6.0) io-console (~> 0.5) request_store (1.7.0) @@ -567,7 +567,7 @@ GEM rubocop-performance (1.23.0) rubocop (>= 1.48.1, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rails (2.27.0) + rubocop-rails (2.28.0) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.52.0, < 2.0) @@ -580,9 +580,9 @@ GEM ffi (~> 1.12) logger rubyzip (2.3.2) - sanitize (6.1.3) + sanitize (7.0.0) crass (~> 1.0.2) - nokogiri (>= 1.12.0) + nokogiri (>= 1.16.8) sass-embedded (1.64.2) google-protobuf (~> 3.23) rake (>= 13.0.0) @@ -630,7 +630,7 @@ GEM terser (1.2.4) execjs (>= 0.3.0, < 3) thor (1.3.2) - tilt (2.4.0) + tilt (2.5.0) timeout (0.4.3) turbo-rails (2.0.11) actionpack (>= 6.0.0) diff --git a/app/assets/javascripts/index/new_note.js b/app/assets/javascripts/index/new_note.js index 887ba043b..885d7d2c9 100644 --- a/app/assets/javascripts/index/new_note.js +++ b/app/assets/javascripts/index/new_note.js @@ -5,7 +5,7 @@ OSM.NewNote = function (map) { content = $("#sidebar_content"), page = {}, addNoteButton = $(".control-note .control-button"), - newNote, + newNoteMarker, halo; var noteIcons = { @@ -35,39 +35,21 @@ OSM.NewNote = function (map) { OSM.router.route("/note/new"); }); - function createNote(marker, form, url) { - var location = marker.getLatLng().wrap(); - - marker.options.draggable = false; - marker.dragging.disable(); - - $(form).find("input[type=submit]").prop("disabled", true); - + function createNote(location, text, callback) { $.ajax({ - url: url, + url: "/api/0.6/notes.json", type: "POST", oauth: true, data: { lat: location.lat, lon: location.lng, - text: $(form.text).val() + text }, - success: function (feature) { - noteCreated(feature, marker); - } + success: callback }); - - function noteCreated(feature, marker) { - content.find("textarea").val(""); - updateMarker(feature); - newNote = null; - noteLayer.removeLayer(marker); - addNoteButton.removeClass("active"); - OSM.router.route("/note/" + feature.properties.id); - } } - function updateMarker(feature) { + function addCreatedNoteMarker(feature) { var marker = L.marker(feature.geometry.coordinates.reverse(), { icon: noteIcons[feature.properties.status], opacity: 0.9, @@ -75,38 +57,78 @@ OSM.NewNote = function (map) { }); marker.id = feature.properties.id; marker.addTo(noteLayer); - return marker; } - page.pushstate = page.popstate = function (path) { - OSM.loadSidebarContent(path, function () { - page.load(path); + function addHalo(latlng) { + if (halo) map.removeLayer(halo); + + halo = L.circleMarker(latlng, { + weight: 2.5, + radius: 20, + fillOpacity: 0.5, + color: "#FF6200" }); - }; - function newHalo(loc, a) { - var hasHalo = halo && map.hasLayer(halo); + map.addLayer(halo); + } - if (a === "dragstart" && hasHalo) { - map.removeLayer(halo); - } else { - if (hasHalo) map.removeLayer(halo); + function removeHalo() { + if (halo) map.removeLayer(halo); + halo = null; + } - halo = L.circleMarker(loc, { - weight: 2.5, - radius: 20, - fillOpacity: 0.5, - color: "#FF6200" - }); + function addNewNoteMarker(latlng) { + if (newNoteMarker) map.removeLayer(newNoteMarker); - map.addLayer(halo); - } + newNoteMarker = L.marker(latlng, { + icon: noteIcons.new, + opacity: 0.9, + draggable: true + }); + + newNoteMarker.on("dragstart dragend", function (a) { + removeHalo(); + if (a.type === "dragend") { + addHalo(newNoteMarker.getLatLng()); + } + }); + + newNoteMarker.addTo(map); + addHalo(newNoteMarker.getLatLng()); + + newNoteMarker.on("dragend", function () { + content.find("textarea").focus(); + }); } - page.load = function (path) { - if (addNoteButton.hasClass("disabled")) return; - if (addNoteButton.hasClass("active")) return; + function removeNewNoteMarker() { + removeHalo(); + if (newNoteMarker) map.removeLayer(newNoteMarker); + newNoteMarker = null; + } + + function moveNewNotMarkerToClick(e) { + if (newNoteMarker) newNoteMarker.setLatLng(e.latlng); + if (halo) halo.setLatLng(e.latlng); + content.find("textarea").focus(); + } + + function updateControls() { + const zoomedOut = addNoteButton.hasClass("disabled"); + const withoutText = content.find("textarea").val() === ""; + content.find("#new-note-zoom-warning").prop("hidden", !zoomedOut); + content.find("input[type=submit]").prop("disabled", zoomedOut || withoutText); + if (newNoteMarker) newNoteMarker.setOpacity(zoomedOut ? 0.5 : 0.9); + } + + page.pushstate = page.popstate = function (path) { + OSM.loadSidebarContent(path, function () { + page.load(path); + }); + }; + + page.load = function (path) { addNoteButton.addClass("active"); map.addLayer(noteLayer); @@ -124,44 +146,39 @@ OSM.NewNote = function (map) { padding: [50, 50] }); - newNote = L.marker(markerLatlng, { - icon: noteIcons.new, - opacity: 0.9, - draggable: true - }); - - newNote.on("dragstart dragend", function (a) { - newHalo(newNote.getLatLng(), a.type); - }); - - newNote.addTo(noteLayer); - newHalo(newNote.getLatLng()); - - newNote.on("remove", function () { - addNoteButton.removeClass("active"); - }).on("dragend", function () { - content.find("textarea").focus(); - }); + addNewNoteMarker(markerLatlng); content.find("textarea") - .on("input", disableWhenBlank) + .on("input", updateControls) .focus(); - function disableWhenBlank(e) { - $(e.target.form.add).prop("disabled", $(e.target).val() === ""); - } - content.find("input[type=submit]").on("click", function (e) { + const location = newNoteMarker.getLatLng().wrap(); + const text = content.find("textarea").val(); + e.preventDefault(); - createNote(newNote, e.target.form, "/api/0.6/notes.json"); + $(this).prop("disabled", true); + newNoteMarker.options.draggable = false; + newNoteMarker.dragging.disable(); + + createNote(location, text, (feature) => { + content.find("textarea").val(""); + addCreatedNoteMarker(feature); + OSM.router.route("/note/" + feature.properties.id); + }); }); + map.on("click", moveNewNotMarkerToClick); + addNoteButton.on("disabled enabled", updateControls); + updateControls(); + return map.getState(); }; page.unload = function () { - if (newNote) noteLayer.removeLayer(newNote); - if (halo) map.removeLayer(halo); + map.off("click", moveNewNotMarkerToClick); + addNoteButton.off("disabled enabled", updateControls); + removeNewNoteMarker(); addNoteButton.removeClass("active"); }; diff --git a/app/assets/javascripts/leaflet.note.js b/app/assets/javascripts/leaflet.note.js index 5f8010967..19fc9392c 100644 --- a/app/assets/javascripts/leaflet.note.js +++ b/app/assets/javascripts/leaflet.note.js @@ -14,12 +14,19 @@ L.OSM.note = function (options) { map.on("zoomend", update); function update() { - var disabled = OSM.STATUS === "database_offline" || map.getZoom() < 12; + var wasDisabled = link.hasClass("disabled"), + isDisabled = OSM.STATUS === "database_offline" || map.getZoom() < 12; link - .toggleClass("disabled", disabled) - .attr("data-bs-original-title", I18n.t(disabled ? + .toggleClass("disabled", isDisabled) + .attr("data-bs-original-title", I18n.t(isDisabled ? "javascripts.site.createnote_disabled_tooltip" : "javascripts.site.createnote_tooltip")); + + if (isDisabled && !wasDisabled) { + link.trigger("disabled"); + } else if (wasDisabled && !isDisabled) { + link.trigger("enabled"); + } } update(); diff --git a/app/views/notes/new.html.erb b/app/views/notes/new.html.erb index c9b1275b9..f461f60e2 100644 --- a/app/views/notes/new.html.erb +++ b/app/views/notes/new.html.erb @@ -9,6 +9,7 @@ :log_in => link_to(t(".anonymous_warning_log_in"), login_path(:referer => new_note_path)), :sign_up => link_to(t(".anonymous_warning_sign_up"), user_new_path) %>

<% end %> +
diff --git a/test/system/create_note_test.rb b/test/system/create_note_test.rb index 435233cbe..5688ec376 100644 --- a/test/system/create_note_test.rb +++ b/test/system/create_note_test.rb @@ -15,6 +15,60 @@ class CreateNoteTest < ApplicationSystemTestCase end end + test "cannot create new note when zoomed out" do + visit new_note_path(:anchor => "map=12/0/0") + + within_sidebar do + assert_no_content "Zoom in to add a note" + assert_button "Add Note", :disabled => true + + fill_in "text", :with => "Some newly added note description" + + assert_no_content "Zoom in to add a note" + assert_button "Add Note", :disabled => false + end + + find(".control-button.zoomout").click + + within_sidebar do + assert_content "Zoom in to add a note" + assert_button "Add Note", :disabled => true + end + + find(".control-button.zoomin").click + + within_sidebar do + assert_no_content "Zoom in to add a note" + assert_button "Add Note", :disabled => false + + click_on "Add Note" + + assert_content "Unresolved note ##{Note.last.id}" + assert_content "Some newly added note description" + end + end + + test "can open new note page when zoomed out" do + visit new_note_path(:anchor => "map=11/0/0") + + within_sidebar do + assert_content "Zoom in to add a note" + assert_button "Add Note", :disabled => true + + fill_in "text", :with => "Some newly added note description" + + assert_content "Zoom in to add a note" + assert_button "Add Note", :disabled => true + end + + find(".control-button.zoomin").click + + within_sidebar do + assert_no_content "Zoom in to add a note" + assert_button "Add Note", :disabled => false + end + end + test "cannot create note when api is readonly" do with_settings(:status => "api_readonly") do visit new_note_path(:anchor => "map=18/0/0")