From c52a65b1064e61a1952e736ca12b28e5bbe767cc Mon Sep 17 00:00:00 2001 From: viditchitkara Date: Wed, 21 Aug 2019 20:36:44 +0530 Subject: [PATCH 1/4] few bug fixes --- .../channels/concurrent_editing.js | 2 +- app/assets/javascripts/mapknitter/Map.js | 123 +++++++++++++++++- app/controllers/images_controller.rb | 7 +- 3 files changed, 122 insertions(+), 10 deletions(-) diff --git a/app/assets/javascripts/channels/concurrent_editing.js b/app/assets/javascripts/channels/concurrent_editing.js index f93e01e45..cc81abbf7 100644 --- a/app/assets/javascripts/channels/concurrent_editing.js +++ b/app/assets/javascripts/channels/concurrent_editing.js @@ -11,7 +11,7 @@ App.concurrent_editing = App.cable.subscriptions.create("ConcurrentEditingChanne received: function(data) { // Called when there's incoming data on the websocket for this channel - window.mapKnitter.synchronizeData(data.changes); + window.mapknitter.synchronizeData(data.changes); }, speak: function(changes) { diff --git a/app/assets/javascripts/mapknitter/Map.js b/app/assets/javascripts/mapknitter/Map.js index c7659757e..a7051a25a 100644 --- a/app/assets/javascripts/mapknitter/Map.js +++ b/app/assets/javascripts/mapknitter/Map.js @@ -405,11 +405,123 @@ MapKnitter.Map = MapKnitter.Class.extend({ corners [2] = y; corners [3] = x; - console.log(corners); - layer = layers.filter(l => l._url==warpable.srcmedium)[0]; - layer.setCorners(corners); + + if(layer == null || layer == undefined) { + window.mapknitter.synchronizeNewAddedImage(warpable); + } else { + layer.setCorners(corners); + var index = layers.indexOf(layer); + if (index > -1) { + layers.splice(index, 1); + } + } }); + + // remove images if deleted from any user's browser + layers.forEach(function(layer) { + edit = layer.editing + edit._removeToolbar(); + edit.disable(); + // remove from Leaflet map: + map.removeLayer(layer); + // remove from sidebar too: + $('#warpable-' + layer.warpable_id).remove(); + }); + }, + + synchronizeNewAddedImage: function(warpable) { + var wn = warpable.nodes; + bounds = []; + + // only already-placed images: + if (wn.length > 0) { + var downloadEl = $('.img-download-' + warpable.id), + imgEl = $('#full-img-' + warpable.id); + + downloadEl.click(function () { + downloadEl.html(''); + + imgEl[0].onload = function () { + var height = imgEl.height(), + width = imgEl.width(), + nw = map.latLngToContainerPoint(wn[0]), + ne = map.latLngToContainerPoint(wn[1]), + se = map.latLngToContainerPoint(wn[2]), + sw = map.latLngToContainerPoint(wn[3]), + offsetX = nw.x, + offsetY = nw.y, + displayedWidth = $('#warpable-img-' + warpable.id).width(), + ratio = width / displayedWidth; + + nw.x -= offsetX; + ne.x -= offsetX; + se.x -= offsetX; + sw.x -= offsetX; + + nw.y -= offsetY; + ne.y -= offsetY; + se.y -= offsetY; + sw.y -= offsetY; + + warpWebGl( + 'full-img-' + warpable.id, + [0, 0, width, 0, width, height, 0, height], + [nw.x, nw.y, ne.x, ne.y, se.x, se.y, sw.x, sw.y], + true // trigger download + ) + + downloadEl.html(''); + } + + imgEl[0].src = $('.img-download-' + warpable.id).attr('data-image'); + }); + + var corners = [ + L.latLng(wn[0].lat, wn[0].lon), + L.latLng(wn[1].lat, wn[1].lon), + L.latLng(wn[3].lat, wn[3].lon), + L.latLng(wn[2].lat, wn[2].lon) + ]; + + var img = L.distortableImageOverlay(warpable.srcmedium, { + corners: corners, + mode: 'lock' + }).addTo(map); + + var customExports = mapknitter.customExportAction(); + var imgGroup = L.distortableCollection({ + actions: [customExports] + }).addTo(map); + + imgGroup.addLayer(img); + + /** + * TODO: toolbar may still appear outside of frame. Create a getter for toolbar corners in LDI and then include them in this calculation + */ + bounds = bounds.concat(corners); + var newImgBounds = L.latLngBounds(corners); + + if (!map._initialBounds.contains(newImgBounds) && !map._initialBounds.equals(newImgBounds)) { + map._initialBounds.extend(newImgBounds); + mapknitter._map.flyToBounds(map._initialBounds); + } + + images.push(img); + img.warpable_id = warpable.id; + + if (!mapknitter.readOnly) { + L.DomEvent.on(img._image, { + click: mapknitter.selectImage, + dblclick: mapknitter.dblClickImage, + load: mapknitter.setupToolbar + }, img); + + L.DomEvent.on(imgGroup, 'layeradd', mapknitter.setupEvents, img); + } + + img.editing.disable() + } }, saveImageIfChanged: function () { @@ -434,7 +546,7 @@ MapKnitter.Map = MapKnitter.Class.extend({ saveImage: function () { var img = this; img._corner_state = JSON.stringify(img._corners); // reset change state string: - $.ajax('/images', { // send save request + $.ajax('/images/'+img.warpable_id, { // send save request type: 'PATCH', data: { warpable_id: img.warpable_id, @@ -474,6 +586,9 @@ MapKnitter.Map = MapKnitter.Class.extend({ beforeSend: function (e) { $('.mk-save').removeClass('fa-check-circle fa-times-circle fa-green fa-red').addClass('fa-spinner fa-spin') }, + success: function(data) { + App.concurrent_editing.speak(data); + }, complete: function (e) { $('.mk-save').removeClass('fa-spinner fa-spin').addClass('fa-check-circle fa-green') // disable interactivity: diff --git a/app/controllers/images_controller.rb b/app/controllers/images_controller.rb index 30213e913..88300b8db 100644 --- a/app/controllers/images_controller.rb +++ b/app/controllers/images_controller.rb @@ -92,10 +92,7 @@ def update @warpable.locked = params[:locked] @warpable.cm_per_pixel = @warpable.get_cm_per_pixel @warpable.save - respond_to do |format| - format.html { render html: 'success' } - format.json { render json: @warpable.map.fetch_map_data } - end + render json: @warpable.map.fetch_map_data else render plain: 'You must be logged in to update the image, unless the map is anonymous.' end @@ -114,7 +111,7 @@ def destroy @warpable.destroy respond_to do |format| format.html { redirect_to @warpable.map } - format.json { render json: @warpable } + format.json { render json: @warpable.map.fetch_map_data } end else flash[:error] = 'You must be logged in to delete images.' From 8470929844b6f674d639859261bdf3d3ac75d4f6 Mon Sep 17 00:00:00 2001 From: viditchitkara Date: Wed, 21 Aug 2019 22:17:17 +0530 Subject: [PATCH 2/4] separate editing channels for different maps --- app/assets/javascripts/channels/concurrent_editing.js | 9 +++++++-- app/channels/concurrent_editing_channel.rb | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/channels/concurrent_editing.js b/app/assets/javascripts/channels/concurrent_editing.js index cc81abbf7..872022784 100644 --- a/app/assets/javascripts/channels/concurrent_editing.js +++ b/app/assets/javascripts/channels/concurrent_editing.js @@ -1,6 +1,10 @@ /* Handles all the frontend interactions with action cable and the server. */ -App.concurrent_editing = App.cable.subscriptions.create("ConcurrentEditingChannel", { +App.concurrent_editing = App.cable.subscriptions.create( + { + channel: "ConcurrentEditingChannel", + mapSlug: window.location.href.split("/").pop() + }, { connected: function() { // Called when the subscription is ready for use on the server }, @@ -20,7 +24,8 @@ App.concurrent_editing = App.cable.subscriptions.create("ConcurrentEditingChanne * which is responsible for broadcasting the updated warpables * to all the user's connected to the concurrent_editing channel. */ return this.perform("sync", { - changes: changes + changes: changes, + map_slug: window.location.href.split("/").pop() }); } }); diff --git a/app/channels/concurrent_editing_channel.rb b/app/channels/concurrent_editing_channel.rb index 79991c3b1..431168def 100644 --- a/app/channels/concurrent_editing_channel.rb +++ b/app/channels/concurrent_editing_channel.rb @@ -3,7 +3,7 @@ class ConcurrentEditingChannel < ApplicationCable::Channel def subscribed # Called first to connect user to the channel. - stream_from "concurrent_editing_channel" + stream_from "concurrent_editing_channel:#{params[:mapSlug]}" end def unsubscribed @@ -12,6 +12,6 @@ def unsubscribed def sync(changes) # Responsible for broadcasting the updated warpables or simply images to the user's connected on this channel. - ActionCable.server.broadcast 'concurrent_editing_channel', changes + ActionCable.server.broadcast "concurrent_editing_channel:#{changes["map_slug"]}", changes end end From 3a24fc9625a11bda6d50502ac771cc774edfa876 Mon Sep 17 00:00:00 2001 From: viditchitkara Date: Wed, 21 Aug 2019 22:41:49 +0530 Subject: [PATCH 3/4] test fixes --- test/controllers/images_controller_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/controllers/images_controller_test.rb b/test/controllers/images_controller_test.rb index 042096f72..41ae79767 100644 --- a/test/controllers/images_controller_test.rb +++ b/test/controllers/images_controller_test.rb @@ -62,7 +62,7 @@ def fetch_in_production points = "-71.39,41.83:-71.39,41.83:-71.39,41.83:-71.39,41.83" patch :update, params: { id: @map.id, warpable_id: @warp.id, locked: false, points: points} assert_not_nil @warp.nodes - assert_equal "text/html", response.content_type + assert_equal "application/json", response.content_type assert_response :success end From 7071ee0fecfb55864d8724e3e0c8b69ded7e0c21 Mon Sep 17 00:00:00 2001 From: viditchitkara Date: Sat, 24 Aug 2019 01:17:09 +0530 Subject: [PATCH 4/4] rubocop fixes --- app/channels/concurrent_editing_channel.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/channels/concurrent_editing_channel.rb b/app/channels/concurrent_editing_channel.rb index 431168def..35ea0bb7c 100644 --- a/app/channels/concurrent_editing_channel.rb +++ b/app/channels/concurrent_editing_channel.rb @@ -12,6 +12,6 @@ def unsubscribed def sync(changes) # Responsible for broadcasting the updated warpables or simply images to the user's connected on this channel. - ActionCable.server.broadcast "concurrent_editing_channel:#{changes["map_slug"]}", changes + ActionCable.server.broadcast "concurrent_editing_channel:#{changes['map_slug']}", changes end end