From 1e3ce68d4338ae70bfc9aa305d63931e372548f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Mon, 25 Nov 2019 15:20:44 +0100 Subject: [PATCH 1/8] javascript fixes --- .../decidim/navigation_maps/map_view.js | 15 ++++++++++++-- .../decidim/navigation_maps/_variables.scss | 3 +++ .../admin/navigation_maps.scss | 17 +++++++--------- .../navigation_maps/navigation_maps.scss | 20 ++++++++++++++++++- 4 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 app/assets/stylesheets/decidim/navigation_maps/_variables.scss diff --git a/app/assets/javascripts/decidim/navigation_maps/map_view.js b/app/assets/javascripts/decidim/navigation_maps/map_view.js index 74448c2..bf7a1d2 100644 --- a/app/assets/javascripts/decidim/navigation_maps/map_view.js +++ b/app/assets/javascripts/decidim/navigation_maps/map_view.js @@ -59,6 +59,15 @@ NavigationMapView.prototype.createAreas = function() { new L.GeoJSON(geoarea, { onEachFeature: function(feature, layer) { layer._leaflet_id = id; + + layer.on('mouseover', function(e) { + e.target.getElement().classList.add('selected') + }); + + layer.on('mouseout', function(e) { + e.target.getElement().classList.remove('selected') + }); + layer.on('click', function(e) { if(feature.properties && feature.properties.link) location = feature.properties.link; }); @@ -77,6 +86,8 @@ NavigationMapView.prototype.forEachBlueprint = function (callback) { }; NavigationMapView.prototype.reload = function () { - this.map.invalidateSize(true); - this.fitBounds(); + if(this.map) { + this.map.invalidateSize(true); + this.fitBounds(); + } }; diff --git a/app/assets/stylesheets/decidim/navigation_maps/_variables.scss b/app/assets/stylesheets/decidim/navigation_maps/_variables.scss new file mode 100644 index 0000000..def41b6 --- /dev/null +++ b/app/assets/stylesheets/decidim/navigation_maps/_variables.scss @@ -0,0 +1,3 @@ +// Variables + +$leaflet-background-color: 34,98,204; diff --git a/app/assets/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss b/app/assets/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss index 705c9fe..a76a6c5 100644 --- a/app/assets/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss +++ b/app/assets/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss @@ -5,10 +5,7 @@ @import "decidim/variables"; @import "decidim/utils/settings"; @import "decidim/utils/mixins"; - -:root { - --leaflet-background-color: 34,98,204; -} +@import "decidim/navigation_maps/variables"; .navigation_maps.admin { .accordion-item { @@ -18,7 +15,7 @@ &.is-active { .accordion-title { background-color: #039be5; - border-color: rgba(var(--leaflet-background-color),1) !important; + border-color: "rgba(#{$leaflet-background-color}, 1)" !important; } } } @@ -79,15 +76,15 @@ } tbody > tr { &.selected { - background-color: rgba(var(--leaflet-background-color), 0.5) !important; + background-color: "rgba(#{$leaflet-background-color}, 0.5)" !important; } &:hover { - background-color: rgba(var(--leaflet-background-color), 0.5) !important; + background-color: "rgba(#{$leaflet-background-color}, 0.5)" !important; } } .leaflet-interactive { - fill: rgba(var(--leaflet-background-color), 1); - color: rgba(var(--leaflet-background-color), 1); + fill: "rgba(#{$leaflet-background-color}, 1)"; + color: "rgba(#{$leaflet-background-color}, 1)"; weight: 3; opacity: 0.6; fill-opacity: 0.5; @@ -96,4 +93,4 @@ } } } -} \ No newline at end of file +} diff --git a/app/assets/stylesheets/decidim/navigation_maps/navigation_maps.scss b/app/assets/stylesheets/decidim/navigation_maps/navigation_maps.scss index 26846ad..07c96f8 100644 --- a/app/assets/stylesheets/decidim/navigation_maps/navigation_maps.scss +++ b/app/assets/stylesheets/decidim/navigation_maps/navigation_maps.scss @@ -2,12 +2,20 @@ //= require leaflet-geoman //= require_self +@import "decidim/navigation_maps/variables"; + .home-section { .navigation_maps { margin: 1em 0; .tabs { background-color: #f4f4f4; } + .tabs-title { + a { + font-size: 1.2em; + color: var(--secondary); + } + } .tabs-content { border-color: #f4f4f4; } @@ -18,5 +26,15 @@ background-color: #fafafa; border-color:#f4f4f4; } + .leaflet-interactive { + fill: "rgba(#{$leaflet-background-color}, 1)"; + color: "rgba(#{$leaflet-background-color}, 1)"; + weight: 3; + opacity: 0.6; + fill-opacity: 0.5; + &.selected { + opacity: 1; + } + } } -} \ No newline at end of file +} From 3daac9c9bb17dc3163a7a398e936ade49209f9b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Mon, 25 Nov 2019 17:18:31 +0100 Subject: [PATCH 2/8] Add model blueprint --- .../decidim/navigation_maps/blueprint.rb | 6 ++-- .../decidim/navigation_maps/blueprint_area.rb | 14 ++++++++ ...decidim_navigation_maps_blueprint_areas.rb | 36 +++++++++++++++++++ lib/decidim/navigation_maps/test/factories.rb | 16 +++++---- spec/model/blueprint_area_spec.rb | 32 +++++++++++++++++ spec/model/blueprint_spec.rb | 30 +++++++++++----- 6 files changed, 116 insertions(+), 18 deletions(-) create mode 100644 app/models/decidim/navigation_maps/blueprint_area.rb create mode 100644 db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb create mode 100644 spec/model/blueprint_area_spec.rb diff --git a/app/models/decidim/navigation_maps/blueprint.rb b/app/models/decidim/navigation_maps/blueprint.rb index 9ad6906..12897f9 100644 --- a/app/models/decidim/navigation_maps/blueprint.rb +++ b/app/models/decidim/navigation_maps/blueprint.rb @@ -7,6 +7,10 @@ class Blueprint < ApplicationRecord self.table_name = "decidim_navigation_maps_blueprints" belongs_to :organization, foreign_key: :decidim_organization_id, class_name: "Decidim::Organization" + has_many :areas, + foreign_key: "decidim_navigation_maps_blueprint_id", + class_name: "Decidim::NavigationMaps::BlueprintArea", + dependent: :destroy validates :organization, presence: true validates :image, @@ -14,8 +18,6 @@ class Blueprint < ApplicationRecord file_content_type: { allow: ["image/jpeg", "image/png", "image/svg+xml"] } mount_uploader :image, Decidim::NavigationMaps::BlueprintUploader - - # validates :blueprint, presence: true end end end diff --git a/app/models/decidim/navigation_maps/blueprint_area.rb b/app/models/decidim/navigation_maps/blueprint_area.rb new file mode 100644 index 0000000..31eb995 --- /dev/null +++ b/app/models/decidim/navigation_maps/blueprint_area.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Decidim + module NavigationMaps + # Abstract class from which all models in this engine inherit. + class BlueprintArea < ApplicationRecord + self.table_name = "decidim_navigation_maps_blueprint_areas" + + belongs_to :blueprint, foreign_key: :decidim_navigation_maps_blueprint_id, class_name: "Decidim::NavigationMaps::Blueprint" + + validates :blueprint, presence: true + end + end +end diff --git a/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb b/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb new file mode 100644 index 0000000..ae6ef06 --- /dev/null +++ b/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +class CreateDecidimNavigationMapsBlueprintAreas < ActiveRecord::Migration[5.2] + class Blueprint < ApplicationRecord + self.table_name = "decidim_navigation_maps_blueprints" + end + + class Area < ApplicationRecord + self.table_name = "decidim_navigation_maps_blueprint_areas" + end + + def change + create_table :decidim_navigation_maps_blueprint_areas do |t| + t.jsonb :area + t.references :decidim_navigation_maps_blueprint, null: false, foreign_key: true, index: { name: "decidim_navigation_maps_constraint_blueprint_id" } + t.jsonb :title, default: {} + t.jsonb :description, default: {} + t.string :area_type + t.string :url + + t.timestamps + end + + # Search areas and create distributed entries + Blueprint.find_each do |blueprint| + blueprint.blueprint.each do |_key, area| + Area.create!( + area: area, + decidim_navigation_maps_blueprint_id: blueprint.id, + area_type: "link", + url: area["properties"]["link"] + ) + end + end + end +end diff --git a/lib/decidim/navigation_maps/test/factories.rb b/lib/decidim/navigation_maps/test/factories.rb index f520f5f..2daca44 100644 --- a/lib/decidim/navigation_maps/test/factories.rb +++ b/lib/decidim/navigation_maps/test/factories.rb @@ -5,13 +5,15 @@ FactoryBot.define do factory :blueprint, class: Decidim::NavigationMaps::Blueprint do organization { create(:organization) } - blueprint { { x: 1, y: 1 } } image { Decidim::Dev.test_file("city.jpeg", "image/jpeg") } - title do - { en: "Tab 1" } - end - description do - { en: "Description for blueprint 1" } - end + title { Decidim::Faker::Localized.word } + description { generate_localized_title } + end + + factory :blueprint_area, class: Decidim::NavigationMaps::BlueprintArea do + blueprint { create(:blueprint) } + area { { x: 1, y: 1 } } + title { Decidim::Faker::Localized.word } + description { generate_localized_title } end end diff --git a/spec/model/blueprint_area_spec.rb b/spec/model/blueprint_area_spec.rb new file mode 100644 index 0000000..174aef6 --- /dev/null +++ b/spec/model/blueprint_area_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + module NavigationMaps + describe BlueprintArea do + subject { blueprint_area } + + let(:organization) { create(:organization) } + let(:blueprint) { create(:blueprint, organization: organization) } + let(:blueprint_area) { build(:blueprint_area, blueprint: blueprint) } + let(:data) { { x: "coord x", y: "coord y" } } + + it { is_expected.to be_valid } + + it "blueprint is associated with organization" do + expect(subject.blueprint).to eq(blueprint) + expect(subject.blueprint.organization).to eq(organization) + end + + # TODO: validate json area + + # context "when no data" do + # let(:data) { [] } + # it "is not valid" do + # expect(subject).not_to be_valid + # end + # end + end + end +end diff --git a/spec/model/blueprint_spec.rb b/spec/model/blueprint_spec.rb index 965113c..1caf738 100644 --- a/spec/model/blueprint_spec.rb +++ b/spec/model/blueprint_spec.rb @@ -8,8 +8,7 @@ module NavigationMaps subject { blueprint } let(:organization) { create(:organization) } - let(:data) { [x: "coord x", y: "coord y"] } - let(:blueprint) { build(:blueprint, blueprint: data, organization: organization) } + let(:blueprint) { create(:blueprint, organization: organization) } it { is_expected.to be_valid } @@ -37,14 +36,27 @@ module NavigationMaps it { is_expected.not_to be_valid } end - # TODO: validate json blueprint + context "when areas are defined" do + let(:blueprint) { build(:blueprint, organization: organization) } - # context "when no data" do - # let(:data) { [] } - # it "is not valid" do - # expect(subject).not_to be_valid - # end - # end + let(:areas) { [area1, area2] } + let(:area1) { create(:blueprint_area, area: data1, blueprint: blueprint) } + let(:area2) { create(:blueprint_area, area: data2, blueprint: blueprint) } + let(:data1) { { x: "coord x", y: "coord y" } } + let(:data2) { { x: "coord x", y: "coord y" } } + + it { is_expected.to be_valid } + + it "areas belong to blueprint" do + expect(area1.blueprint).to eq(blueprint) + expect(area2.blueprint).to eq(blueprint) + end + + it "blueprint contains areas" do + expect(blueprint.areas).to include(area1) + expect(blueprint.areas).to include(area2) + end + end end end end From 04ae57627c19bffd2d95b16971f11f483e5d1f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Mon, 25 Nov 2019 18:08:28 +0100 Subject: [PATCH 3/8] compatible blueprint json generator --- .../decidim/navigation_maps/blueprint.rb | 6 +++++ ...decidim_navigation_maps_blueprint_areas.rb | 4 ++++ spec/model/blueprint_spec.rb | 24 ++++++++++++++----- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/app/models/decidim/navigation_maps/blueprint.rb b/app/models/decidim/navigation_maps/blueprint.rb index 12897f9..88ae9b6 100644 --- a/app/models/decidim/navigation_maps/blueprint.rb +++ b/app/models/decidim/navigation_maps/blueprint.rb @@ -18,6 +18,12 @@ class Blueprint < ApplicationRecord file_content_type: { allow: ["image/jpeg", "image/png", "image/svg+xml"] } mount_uploader :image, Decidim::NavigationMaps::BlueprintUploader + + def blueprint + areas.map do |area| + [area.id.to_s, area.area] + end.to_h + end end end end diff --git a/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb b/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb index ae6ef06..b7abed0 100644 --- a/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb +++ b/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb @@ -23,6 +23,8 @@ def change # Search areas and create distributed entries Blueprint.find_each do |blueprint| + next unless blueprint.blueprint + blueprint.blueprint.each do |_key, area| Area.create!( area: area, @@ -32,5 +34,7 @@ def change ) end end + + remove_column :decidim_navigation_maps_blueprints, :blueprint, :jsonb end end diff --git a/spec/model/blueprint_spec.rb b/spec/model/blueprint_spec.rb index 1caf738..c61cd78 100644 --- a/spec/model/blueprint_spec.rb +++ b/spec/model/blueprint_spec.rb @@ -37,24 +37,36 @@ module NavigationMaps end context "when areas are defined" do - let(:blueprint) { build(:blueprint, organization: organization) } + let!(:blueprint) { create(:blueprint, organization: organization) } + let!(:area1) { create(:blueprint_area, area: data1, blueprint: blueprint) } + let!(:area2) { create(:blueprint_area, area: data2, blueprint: blueprint) } - let(:areas) { [area1, area2] } - let(:area1) { create(:blueprint_area, area: data1, blueprint: blueprint) } - let(:area2) { create(:blueprint_area, area: data2, blueprint: blueprint) } - let(:data1) { { x: "coord x", y: "coord y" } } - let(:data2) { { x: "coord x", y: "coord y" } } + let(:blueprint_object) do + { + area1.id.to_s => data1, + area2.id.to_s => data2 + } + end + let(:area3) { create(:blueprint_area, area: data2) } + let(:data1) { { "x" => "coord x", "y" => "coord y" } } + let(:data2) { { "x" => "coord x", "y" => "coord y" } } it { is_expected.to be_valid } it "areas belong to blueprint" do expect(area1.blueprint).to eq(blueprint) expect(area2.blueprint).to eq(blueprint) + expect(area3.blueprint).not_to eq(blueprint) end it "blueprint contains areas" do expect(blueprint.areas).to include(area1) expect(blueprint.areas).to include(area2) + expect(blueprint.areas).not_to include(area3) + end + + it "compacts json areas in a single object" do + expect(blueprint.blueprint).to eq(blueprint_object) end end end From a9f52d646a8e991d585e84b56967e6bded725fd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Mon, 25 Nov 2019 18:57:59 +0100 Subject: [PATCH 4/8] area refactor --- .../navigation_maps/create_blueprints.rb | 18 +++++++++++++++++- .../decidim/navigation_maps/blueprint.rb | 6 +++++- ..._decidim_navigation_maps_blueprint_areas.rb | 4 ++-- lib/decidim/navigation_maps/test/factories.rb | 2 ++ spec/commands/create_blueprints_spec.rb | 15 +++++++++++++-- spec/model/blueprint_spec.rb | 16 ++++++++++++++-- 6 files changed, 53 insertions(+), 8 deletions(-) diff --git a/app/commands/decidim/navigation_maps/create_blueprints.rb b/app/commands/decidim/navigation_maps/create_blueprints.rb index 852a427..e8d91cb 100644 --- a/app/commands/decidim/navigation_maps/create_blueprints.rb +++ b/app/commands/decidim/navigation_maps/create_blueprints.rb @@ -26,6 +26,8 @@ def call if form.remove destroy_blueprint!(form) else + delete_areas + create_areas(form.blueprint) if form.blueprint update_blueprint!(form) end end @@ -45,7 +47,6 @@ def create_blueprint(form) def update_blueprint!(form) @blueprint.image = form.image if form.image.present? - @blueprint.blueprint = form.blueprint @blueprint.title = form.title @blueprint.description = form.description @blueprint.save! @@ -54,6 +55,21 @@ def update_blueprint!(form) def destroy_blueprint!(form) @blueprint.destroy! if form.id end + + def delete_areas + @blueprint.areas.destroy_all + end + + def create_areas(blueprint) + blueprint.each do |_key, area| + BlueprintArea.create!( + blueprint: @blueprint, + area: area[:geometry], + area_type: area[:type], + url: area[:properties][:link] + ) + end + end end end end diff --git a/app/models/decidim/navigation_maps/blueprint.rb b/app/models/decidim/navigation_maps/blueprint.rb index 88ae9b6..0a18275 100644 --- a/app/models/decidim/navigation_maps/blueprint.rb +++ b/app/models/decidim/navigation_maps/blueprint.rb @@ -21,7 +21,11 @@ class Blueprint < ApplicationRecord def blueprint areas.map do |area| - [area.id.to_s, area.area] + [area.id.to_s, { + type: area.area_type, + geometry: area.area, + properties: { link: area.url } + }] end.to_h end end diff --git a/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb b/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb index b7abed0..ec5b50c 100644 --- a/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb +++ b/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb @@ -27,9 +27,9 @@ def change blueprint.blueprint.each do |_key, area| Area.create!( - area: area, + area: area["geometry"], decidim_navigation_maps_blueprint_id: blueprint.id, - area_type: "link", + area_type: area["type"], url: area["properties"]["link"] ) end diff --git a/lib/decidim/navigation_maps/test/factories.rb b/lib/decidim/navigation_maps/test/factories.rb index 2daca44..93d2277 100644 --- a/lib/decidim/navigation_maps/test/factories.rb +++ b/lib/decidim/navigation_maps/test/factories.rb @@ -13,6 +13,8 @@ factory :blueprint_area, class: Decidim::NavigationMaps::BlueprintArea do blueprint { create(:blueprint) } area { { x: 1, y: 1 } } + area_type { "Feature" } + url { "#" } title { Decidim::Faker::Localized.word } description { generate_localized_title } end diff --git a/spec/commands/create_blueprints_spec.rb b/spec/commands/create_blueprints_spec.rb index 0aad866..6bc488f 100644 --- a/spec/commands/create_blueprints_spec.rb +++ b/spec/commands/create_blueprints_spec.rb @@ -18,7 +18,7 @@ module Decidim::NavigationMaps let(:form1) do double( BlueprintForm, - blueprint: data, + blueprint: blueprint_object, id: id, title: title, description: title, @@ -29,7 +29,7 @@ module Decidim::NavigationMaps let(:form2) do double( BlueprintForm, - blueprint: data, + blueprint: blueprint_object, id: 2, title: title, description: nil, @@ -37,6 +37,17 @@ module Decidim::NavigationMaps image: nil ) end + let(:blueprint_object) do + { + "1" => { + type: "Feature", + geometry: data, + properties: { + link: "#" + } + } + } + end let(:data) do { x: 0.5, y: 0.6 } end diff --git a/spec/model/blueprint_spec.rb b/spec/model/blueprint_spec.rb index c61cd78..58d24a9 100644 --- a/spec/model/blueprint_spec.rb +++ b/spec/model/blueprint_spec.rb @@ -43,8 +43,20 @@ module NavigationMaps let(:blueprint_object) do { - area1.id.to_s => data1, - area2.id.to_s => data2 + area1.id.to_s => { + type: "Feature", + geometry: data1, + properties: { + link: "#" + } + }, + area2.id.to_s => { + type: "Feature", + geometry: data2, + properties: { + link: "#" + } + } } end let(:area3) { create(:blueprint_area, area: data2) } From cc2c50e235b06c2041bf94ab1fbd8309ce421bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Tue, 26 Nov 2019 10:29:38 +0100 Subject: [PATCH 5/8] add ajax controller for areas in blueprints --- .../navigation_maps/admin/map_editor.js | 5 ++ .../navigation_maps/admin/navigation_maps.js | 33 ++++++++++- .../decidim/navigation_maps/map_view.js | 8 ++- .../navigation_maps/navigation_maps.js | 8 ++- .../admin/navigation_maps.scss | 18 +++++- .../navigation_map_settings_form/_modal.erb | 12 ++++ .../navigation_map_settings_form/show.erb | 3 + .../decidim/navigation_maps/save_area.rb | 49 ++++++++++++++++ ...reate_blueprints.rb => save_blueprints.rb} | 9 ++- .../navigation_maps/admin/areas_controller.rb | 49 ++++++++++++++++ .../admin/blueprints_controller.rb | 11 +++- .../decidim/navigation_maps/area_form.rb | 18 ++++++ .../decidim/navigation_maps/blueprint.rb | 3 +- .../admin/areas/_form.html.erb | 3 + .../navigation_maps/admin/areas/new.html.erb | 1 + .../navigation_maps/admin/areas/show.html.erb | 14 +++++ config/locales/en.yml | 9 +++ ...decidim_navigation_maps_blueprint_areas.rb | 8 +++ lib/decidim/navigation_maps/admin_engine.rb | 5 +- lib/decidim/navigation_maps/test/factories.rb | 2 +- spec/commands/save_area_spec.rb | 56 +++++++++++++++++++ ...prints_spec.rb => save_blueprints_spec.rb} | 7 +-- spec/forms/area_form_spec.rb | 35 ++++++++++++ spec/model/blueprint_area_spec.rb | 44 ++++++++++++--- spec/model/blueprint_spec.rb | 10 +--- 25 files changed, 380 insertions(+), 40 deletions(-) create mode 100644 app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/_modal.erb create mode 100644 app/commands/decidim/navigation_maps/save_area.rb rename app/commands/decidim/navigation_maps/{create_blueprints.rb => save_blueprints.rb} (89%) create mode 100644 app/controllers/decidim/navigation_maps/admin/areas_controller.rb create mode 100644 app/forms/decidim/navigation_maps/area_form.rb create mode 100644 app/views/decidim/navigation_maps/admin/areas/_form.html.erb create mode 100644 app/views/decidim/navigation_maps/admin/areas/new.html.erb create mode 100644 app/views/decidim/navigation_maps/admin/areas/show.html.erb create mode 100644 db/migrate/20191126045831_add_link_type_to_decidim_navigation_maps_blueprint_areas.rb create mode 100644 spec/commands/save_area_spec.rb rename spec/commands/{create_blueprints_spec.rb => save_blueprints_spec.rb} (95%) create mode 100644 spec/forms/area_form_spec.rb diff --git a/app/assets/javascripts/decidim/navigation_maps/admin/map_editor.js b/app/assets/javascripts/decidim/navigation_maps/admin/map_editor.js index bf1b838..f1c1795 100644 --- a/app/assets/javascripts/decidim/navigation_maps/admin/map_editor.js +++ b/app/assets/javascripts/decidim/navigation_maps/admin/map_editor.js @@ -11,6 +11,7 @@ function NavigationMapEditor(map_object, table_object) { }; }); self.table_object = table_object; + this.onAreaCallback = function () {}; } // NavigationMapEditor derives from NavigationMapView @@ -60,6 +61,10 @@ NavigationMapView.prototype.createAreas = function() { self.blueprint[e.target._leaflet_id] = e.target.toGeoJSON(); }); + layer.on('click', function(e) { + self.clickAreaCallback(e.target._leaflet_id, e.target, self); + }); + self.renderRow(layer, feature); } }).addTo(self.map); diff --git a/app/assets/javascripts/decidim/navigation_maps/admin/navigation_maps.js b/app/assets/javascripts/decidim/navigation_maps/admin/navigation_maps.js index 2110b45..8e9e80c 100644 --- a/app/assets/javascripts/decidim/navigation_maps/admin/navigation_maps.js +++ b/app/assets/javascripts/decidim/navigation_maps/admin/navigation_maps.js @@ -13,16 +13,45 @@ $(function() { var $bar = $('.navigation_maps.admin .progress-meter'); var $loading = $('.navigation_maps.admin .loading'); var $callout = $('.navigation_maps.admin .callout'); + var $modal = $('#mapEditModal'); var $form = $('form'); var $tabs = $('#navigation_maps-tabs'); var $accordion = $('.navigation_maps.admin .accordion'); var editors = {}; $maps.each(function() { - var table = document.getElementById("navigation_maps-table-" + $(this).data('id')); - editors[$(this).data('id')] = new NavigationMapEditor(this, table); + var id = $(this).data('id'); + var table = document.getElementById("navigation_maps-table-" + id); + editors[id] = new NavigationMapEditor(this, table); + editors[id].onClickArea(function(area_id, area, obj) { + $modal.find('.modal-content').html(''); + $modal.addClass('loading').foundation('open'); + $callout.hide(); + $callout.removeClass('alert success'); + $modal.find('.modal-content').load(`/admin/navigation_maps/blueprints/${id}/areas/${area_id}`, function() { + $modal.removeClass('loading'); + }); + }); + }); + + // Rails AJAX events + document.body.addEventListener('ajax:error', function(responseText) { + $callout.contents('p').html(responseText.detail[0].message + ": " + responseText.detail[0].error + ""); + $callout.addClass('alert'); }); + document.body.addEventListener('ajax:success', function(responseText) { + console.log(responseText); + $callout.contents('p').html(responseText.detail[0].message); + $callout.addClass('success'); + }); + + document.body.addEventListener('ajax:complete', function(xhr, event) { + console.log(event, xhr) + $callout.show(); + $modal.foundation('close'); + }) + $tabs.on('change.zf.tabs', function(e, $tab, $content) { var id = $content.find('.map').data('id'); if(id) { diff --git a/app/assets/javascripts/decidim/navigation_maps/map_view.js b/app/assets/javascripts/decidim/navigation_maps/map_view.js index bf7a1d2..f65c4c9 100644 --- a/app/assets/javascripts/decidim/navigation_maps/map_view.js +++ b/app/assets/javascripts/decidim/navigation_maps/map_view.js @@ -19,6 +19,7 @@ function NavigationMapView(map_object, callback) { } }; self.image.src = self.image_path; + this.clickAreaCallback = function () {}; } NavigationMapView.prototype.createMap = function() { @@ -69,13 +70,18 @@ NavigationMapView.prototype.createAreas = function() { }); layer.on('click', function(e) { - if(feature.properties && feature.properties.link) location = feature.properties.link; + self.clickAreaCallback(e.target, self); }); } }).addTo(self.map); }); }; +// register callback to handle area clicks +NavigationMapView.prototype.onClickArea = function(callback) { + this.clickAreaCallback = callback; +}; + NavigationMapView.prototype.forEachBlueprint = function (callback) { for (var id in this.blueprint) { var geoarea = this.blueprint[id]; diff --git a/app/assets/javascripts/decidim/navigation_maps/navigation_maps.js b/app/assets/javascripts/decidim/navigation_maps/navigation_maps.js index 530061c..d460a47 100644 --- a/app/assets/javascripts/decidim/navigation_maps/navigation_maps.js +++ b/app/assets/javascripts/decidim/navigation_maps/navigation_maps.js @@ -13,7 +13,11 @@ $(function() { var maps = {}; $maps.each(function() { - maps[$(this).data('id')] = new NavigationMapView(this); + var id = $(this).data('id'); + maps[id] = new NavigationMapView(this); + maps[id].onClickArea(function(area) { + if(area.feature.properties && area.feature.properties.link) location = area.feature.properties.link; + }); }); $tabs.on('change.zf.tabs', function(e, $tab, $content) { @@ -21,4 +25,4 @@ $(function() { maps[id].reload(); }); -}); \ No newline at end of file +}); diff --git a/app/assets/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss b/app/assets/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss index a76a6c5..9969ba6 100644 --- a/app/assets/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss +++ b/app/assets/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss @@ -41,7 +41,7 @@ } .spinner { - @include spinner(25px, #aaa, var(--primary), 800ms); + @include spinner(25px, #aaa, var(--secondary), 800ms); vertical-align: middle; } .progress { @@ -52,7 +52,7 @@ } .progress-meter { color: #fff; - background-color: var(--primary); + background-color: var(--secondary); width: 30%; padding:0 0.5em; font-size: 0.7em; @@ -93,4 +93,18 @@ } } } + +} + +.navigation_maps.modal { + .spinner { + @include spinner(25px, #aaa, var(--secondary), 800ms); + vertical-align: middle; + display: none; + } + &.loading { + .spinner { + display: inline-block; + } + } } diff --git a/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/_modal.erb b/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/_modal.erb new file mode 100644 index 0000000..98cbd8e --- /dev/null +++ b/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/_modal.erb @@ -0,0 +1,12 @@ + + diff --git a/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/show.erb b/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/show.erb index f18621a..d060506 100644 --- a/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/show.erb +++ b/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/show.erb @@ -15,6 +15,8 @@ <%= render partial: "tabs", locals: { tabs: blueprints } %> <%= render partial: "tabs_content", locals: { tabs: blueprints } %> + +
@@ -26,5 +28,6 @@
+<%= render partial: "modal" %> <%= javascript_include_tag "decidim/navigation_maps/admin/navigation_maps" %> <%= stylesheet_link_tag "decidim/navigation_maps/admin/navigation_maps" %> diff --git a/app/commands/decidim/navigation_maps/save_area.rb b/app/commands/decidim/navigation_maps/save_area.rb new file mode 100644 index 0000000..f84ffcc --- /dev/null +++ b/app/commands/decidim/navigation_maps/save_area.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module Decidim + module NavigationMaps + # This command creates or updates areas for a blueprints + class SaveArea < Rectify::Command + # Creates or updates an area for a blueprint. + # + # form - The form with the data. + def initialize(form) + @form = form + end + + # Executes the command. Broadcasts these events: + # + # - :ok when everything is valid + # - :invalid if the form wasn't valid and we couldn't proceed. + # + # Returns nothing. + def call + return broadcast(:invalid, form.errors.full_messages.join(", ")) if form.invalid? + + initialize_area + update_area + save_area! + + broadcast(:ok) + end + + private + + attr_reader :form + + def initialize_area + @area = BlueprintArea.find_or_initialize_by(id: form.id) do |area| + area.blueprint = form.current_blueprint + end + end + + def update_area + @area.link = form.link + end + + def save_area! + @area.save! + end + end + end +end diff --git a/app/commands/decidim/navigation_maps/create_blueprints.rb b/app/commands/decidim/navigation_maps/save_blueprints.rb similarity index 89% rename from app/commands/decidim/navigation_maps/create_blueprints.rb rename to app/commands/decidim/navigation_maps/save_blueprints.rb index e8d91cb..03f6d3e 100644 --- a/app/commands/decidim/navigation_maps/create_blueprints.rb +++ b/app/commands/decidim/navigation_maps/save_blueprints.rb @@ -3,7 +3,7 @@ module Decidim module NavigationMaps # This command creates or updates the blueprints for the organization. - class CreateBlueprints < Rectify::Command + class SaveBlueprints < Rectify::Command # Creates a blueprint. # # forms - The form with the data. @@ -22,7 +22,7 @@ def call @blueprints.each do |form| next if form.invalid? - create_blueprint(form) + initialize_blueprint(form) if form.remove destroy_blueprint!(form) else @@ -39,7 +39,7 @@ def call attr_reader :forms - def create_blueprint(form) + def initialize_blueprint(form) @blueprint = Blueprint.find_or_initialize_by(id: form.id) do |blueprint| blueprint.organization = @forms.current_organization end @@ -65,8 +65,7 @@ def create_areas(blueprint) BlueprintArea.create!( blueprint: @blueprint, area: area[:geometry], - area_type: area[:type], - url: area[:properties][:link] + area_type: area[:type] ) end end diff --git a/app/controllers/decidim/navigation_maps/admin/areas_controller.rb b/app/controllers/decidim/navigation_maps/admin/areas_controller.rb new file mode 100644 index 0000000..e381d70 --- /dev/null +++ b/app/controllers/decidim/navigation_maps/admin/areas_controller.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module Decidim + module NavigationMaps + module Admin + class AreasController < ::Decidim::NavigationMaps::Admin::ApplicationController + layout false + + before_action do + enforce_permission_to :update, :organization, organization: current_organization + end + + def index + render json: blueprint.areas + end + + def new; end + + def show + @form = AreaForm.from_model(area) + end + + def update + @form = form(AreaForm).from_params(params, current_blueprint: blueprint) + + SaveArea.call(@form) do + on(:ok) do |_message| + render json: { message: I18n.t("navigation_maps.admin.areas.update.success", scope: "decidim") } + end + + on(:invalid) do |message| + render json: { message: I18n.t("navigation_maps.admin.areas.update.error", scope: "decidim"), error: message }, status: :unprocessable_entity + end + end + end + + private + + def blueprint + @blueprint ||= Blueprint.find(params[:blueprint_id]) + end + + def area + @area ||= BlueprintArea.find(params[:id]) + end + end + end + end +end diff --git a/app/controllers/decidim/navigation_maps/admin/blueprints_controller.rb b/app/controllers/decidim/navigation_maps/admin/blueprints_controller.rb index 27617b3..4c56966 100644 --- a/app/controllers/decidim/navigation_maps/admin/blueprints_controller.rb +++ b/app/controllers/decidim/navigation_maps/admin/blueprints_controller.rb @@ -4,15 +4,22 @@ module Decidim module NavigationMaps module Admin class BlueprintsController < ::Decidim::NavigationMaps::Admin::ApplicationController + before_action do + enforce_permission_to :update, :organization, organization: current_organization + end + def index render json: organization_blueprints end + def show + render json: organization_blueprints.find(params[:id]) + end + def create - enforce_permission_to :update, :organization, organization: current_organization parse_blueprints @form = form(BlueprintForms).from_params(params).with_context(current_organization: current_organization) - CreateBlueprints.call(@form) do + SaveBlueprints.call(@form) do on(:ok) do render plain: I18n.t("navigation_maps.create.success", scope: "decidim") end diff --git a/app/forms/decidim/navigation_maps/area_form.rb b/app/forms/decidim/navigation_maps/area_form.rb new file mode 100644 index 0000000..e6233bc --- /dev/null +++ b/app/forms/decidim/navigation_maps/area_form.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module Decidim + module NavigationMaps + # A form object used to configure the blueprint content block from the admin panel. + # + class AreaForm < Decidim::Form + include TranslatableAttributes + + mimic :blueprint_area + + attribute :area, Object + attribute :link, String + translatable_attribute :title, String + translatable_attribute :description, String + end + end +end diff --git a/app/models/decidim/navigation_maps/blueprint.rb b/app/models/decidim/navigation_maps/blueprint.rb index 0a18275..debd1a6 100644 --- a/app/models/decidim/navigation_maps/blueprint.rb +++ b/app/models/decidim/navigation_maps/blueprint.rb @@ -23,8 +23,7 @@ def blueprint areas.map do |area| [area.id.to_s, { type: area.area_type, - geometry: area.area, - properties: { link: area.url } + geometry: area.area }] end.to_h end diff --git a/app/views/decidim/navigation_maps/admin/areas/_form.html.erb b/app/views/decidim/navigation_maps/admin/areas/_form.html.erb new file mode 100644 index 0000000..69a261c --- /dev/null +++ b/app/views/decidim/navigation_maps/admin/areas/_form.html.erb @@ -0,0 +1,3 @@ +
+ <%= form.text_field :link %> +
diff --git a/app/views/decidim/navigation_maps/admin/areas/new.html.erb b/app/views/decidim/navigation_maps/admin/areas/new.html.erb new file mode 100644 index 0000000..3e75765 --- /dev/null +++ b/app/views/decidim/navigation_maps/admin/areas/new.html.erb @@ -0,0 +1 @@ +new diff --git a/app/views/decidim/navigation_maps/admin/areas/show.html.erb b/app/views/decidim/navigation_maps/admin/areas/show.html.erb new file mode 100644 index 0000000..18f6f58 --- /dev/null +++ b/app/views/decidim/navigation_maps/admin/areas/show.html.erb @@ -0,0 +1,14 @@ +<%= decidim_form_for(@form, url: blueprint_area_path, remote: true) do |f| %> +
+
+

#<%= @form.id %>: <%= t ".area" %>

+
+
+ <%= render partial: "form", object: f %> +
+
+
+ <%= f.submit t(".save") %> + +
+<% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index e9f1277..e2cb3cf 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -5,6 +5,15 @@ en: navigation_maps: name: NavigationMaps navigation_maps: + admin: + areas: + show: + area: Area details + save: Save + cancel: Cancel + update: + success: Area saved successfully + error: An error ocurred while saving the area content_blocks: name: Navigation Maps navigation_map_settings_form: diff --git a/db/migrate/20191126045831_add_link_type_to_decidim_navigation_maps_blueprint_areas.rb b/db/migrate/20191126045831_add_link_type_to_decidim_navigation_maps_blueprint_areas.rb new file mode 100644 index 0000000..97bc0cb --- /dev/null +++ b/db/migrate/20191126045831_add_link_type_to_decidim_navigation_maps_blueprint_areas.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class AddLinkTypeToDecidimNavigationMapsBlueprintAreas < ActiveRecord::Migration[5.2] + def change + rename_column :decidim_navigation_maps_blueprint_areas, :url, :link + add_column :decidim_navigation_maps_blueprint_areas, :link_type, :string + end +end diff --git a/lib/decidim/navigation_maps/admin_engine.rb b/lib/decidim/navigation_maps/admin_engine.rb index 9826dd8..3b1fb75 100644 --- a/lib/decidim/navigation_maps/admin_engine.rb +++ b/lib/decidim/navigation_maps/admin_engine.rb @@ -11,8 +11,9 @@ class AdminEngine < ::Rails::Engine routes do # Add admin engine routes here - resources :blueprints, only: [:index, :create, :destroy] - # root to: "navigation_maps#index" + resources :blueprints, only: [:index, :show, :create] do + resources :areas + end end initializer "decidim_navigation_maps.admin_mount_routes" do diff --git a/lib/decidim/navigation_maps/test/factories.rb b/lib/decidim/navigation_maps/test/factories.rb index 93d2277..67dc541 100644 --- a/lib/decidim/navigation_maps/test/factories.rb +++ b/lib/decidim/navigation_maps/test/factories.rb @@ -14,7 +14,7 @@ blueprint { create(:blueprint) } area { { x: 1, y: 1 } } area_type { "Feature" } - url { "#" } + link { "#" } title { Decidim::Faker::Localized.word } description { generate_localized_title } end diff --git a/spec/commands/save_area_spec.rb b/spec/commands/save_area_spec.rb new file mode 100644 index 0000000..6ee744c --- /dev/null +++ b/spec/commands/save_area_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim::NavigationMaps + describe SaveArea do + subject { described_class.new(form) } + + let(:blueprint) { create :blueprint } + let(:form) do + double( + AreaForm, + area: data, + id: id, + title: title, + description: title, + link: link, + current_blueprint: blueprint + ) + end + let(:data) do + { x: 0.5, y: 0.6 } + end + let(:title) { Decidim::Faker::Localized.sentence(2) } + let(:description) { Decidim::Faker::Localized.paragraph } + let(:id) { nil } + let(:link) { "#link" } + + before do + allow(form).to receive(:invalid?).and_return(false) + end + + context "when everything is ok" do + it "broadcasts ok" do + expect { subject.call }.to broadcast(:ok) + end + + it "creates the area" do + expect { subject.call }.to change(BlueprintArea, :count).by(1) + end + end + + context "when id exists" do + let!(:area) { create(:blueprint_area, blueprint: blueprint) } + let(:id) { area.id } + + it "broadcasts ok" do + expect { subject.call }.to broadcast(:ok) + end + + it "creates the area" do + expect { subject.call }.to change(BlueprintArea, :count).by(0) + end + end + end +end diff --git a/spec/commands/create_blueprints_spec.rb b/spec/commands/save_blueprints_spec.rb similarity index 95% rename from spec/commands/create_blueprints_spec.rb rename to spec/commands/save_blueprints_spec.rb index 6bc488f..cf4661a 100644 --- a/spec/commands/create_blueprints_spec.rb +++ b/spec/commands/save_blueprints_spec.rb @@ -3,7 +3,7 @@ require "spec_helper" module Decidim::NavigationMaps - describe CreateBlueprints do + describe SaveBlueprints do subject { described_class.new(forms) } let(:organization) { create :organization } @@ -41,10 +41,7 @@ module Decidim::NavigationMaps { "1" => { type: "Feature", - geometry: data, - properties: { - link: "#" - } + geometry: data } } end diff --git a/spec/forms/area_form_spec.rb b/spec/forms/area_form_spec.rb new file mode 100644 index 0000000..26af323 --- /dev/null +++ b/spec/forms/area_form_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim::NavigationMaps + describe AreaForm do + subject { described_class.from_params(attributes).with_context(context) } + + let(:blueprint) { create :blueprint } + let(:title) { Decidim::Faker::Localized.sentence(2) } + let(:description) { Decidim::Faker::Localized.paragraph } + let(:area) do + { + "x" => "x data", + "y" => "y data" + } + end + let(:attributes) do + { + title: title, + description: description, + area: area + } + end + let(:context) do + { + "current_blueprint" => blueprint + } + end + + context "when everything is OK" do + it { is_expected.to be_valid } + end + end +end diff --git a/spec/model/blueprint_area_spec.rb b/spec/model/blueprint_area_spec.rb index 174aef6..24eb36b 100644 --- a/spec/model/blueprint_area_spec.rb +++ b/spec/model/blueprint_area_spec.rb @@ -9,8 +9,16 @@ module NavigationMaps let(:organization) { create(:organization) } let(:blueprint) { create(:blueprint, organization: organization) } - let(:blueprint_area) { build(:blueprint_area, blueprint: blueprint) } - let(:data) { { x: "coord x", y: "coord y" } } + let(:blueprint_area) { build(:blueprint_area, title: title, description: description, link: link, area: area, blueprint: blueprint) } + let(:area) do + { + "x" => "coord x", + "y" => "coord y" + } + end + let(:title) { Decidim::Faker::Localized.sentence(2) } + let(:description) { Decidim::Faker::Localized.paragraph } + let(:link) { "#link" } it { is_expected.to be_valid } @@ -20,13 +28,33 @@ module NavigationMaps end # TODO: validate json area + context "when all fields are specified" do + it "saves data correctly" do + subject.save + subject.reload + expect(subject.title).to eq(title) + expect(subject.description).to eq(description) + expect(subject.link).to eq(link) + expect(subject.area).to eq(area) + end + end - # context "when no data" do - # let(:data) { [] } - # it "is not valid" do - # expect(subject).not_to be_valid - # end - # end + context "when no area" do + let!(:blueprint_area) { create(:blueprint_area, title: title, description: description, link: link, area: area, blueprint: blueprint) } + + it "save data without area" do + a = BlueprintArea.find(blueprint_area.id) + a.title = title + a.description = description + a.link = link + a.save + # a.reload + expect(a.title).to eq(title) + expect(a.description).to eq(description) + expect(a.link).to eq(link) + expect(a.area).to eq(area) + end + end end end end diff --git a/spec/model/blueprint_spec.rb b/spec/model/blueprint_spec.rb index 58d24a9..9a17c90 100644 --- a/spec/model/blueprint_spec.rb +++ b/spec/model/blueprint_spec.rb @@ -45,17 +45,11 @@ module NavigationMaps { area1.id.to_s => { type: "Feature", - geometry: data1, - properties: { - link: "#" - } + geometry: data1 }, area2.id.to_s => { type: "Feature", - geometry: data2, - properties: { - link: "#" - } + geometry: data2 } } end From 2fdd69246b0dc697170963ded3dba9902da415e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Tue, 26 Nov 2019 17:55:01 +0100 Subject: [PATCH 6/8] Editor with modal --- .../navigation_maps/admin/map_editor.js | 87 ++++++++----------- .../navigation_maps/admin/navigation_maps.js | 23 +++-- .../decidim/navigation_maps/map_view.js | 2 + .../navigation_maps/navigation_maps.js | 2 - .../admin/navigation_maps.scss | 8 -- .../decidim/navigation_maps/save_area.rb | 11 +-- .../navigation_maps/save_blueprints.rb | 5 +- .../navigation_maps/admin/areas_controller.rb | 36 ++++++-- .../decidim/navigation_maps/area_form.rb | 2 + .../decidim/navigation_maps/blueprint.rb | 7 +- .../decidim/navigation_maps/blueprint_area.rb | 10 +++ .../navigation_maps/admin/areas/new.html.erb | 18 +++- config/locales/en.yml | 7 ++ ...decidim_navigation_maps_blueprint_areas.rb | 14 +++ lib/decidim/navigation_maps/admin_engine.rb | 2 +- spec/commands/save_area_spec.rb | 17 +++- .../decidim/area_controller_spec.rb | 72 +++++++++++++++ .../decidim/blueprint_controller_spec.rb | 2 +- 18 files changed, 238 insertions(+), 87 deletions(-) create mode 100644 db/migrate/20191126154019_add_area_id_to_decidim_navigation_maps_blueprint_areas.rb create mode 100644 spec/controllers/decidim/area_controller_spec.rb diff --git a/app/assets/javascripts/decidim/navigation_maps/admin/map_editor.js b/app/assets/javascripts/decidim/navigation_maps/admin/map_editor.js index f1c1795..ff7331a 100644 --- a/app/assets/javascripts/decidim/navigation_maps/admin/map_editor.js +++ b/app/assets/javascripts/decidim/navigation_maps/admin/map_editor.js @@ -11,7 +11,9 @@ function NavigationMapEditor(map_object, table_object) { }; }); self.table_object = table_object; - this.onAreaCallback = function () {}; + this.createAreaCallback = function () {}; + this.editAreaCallback = function () {}; + this.removeAreaCallback = function () {}; } // NavigationMapEditor derives from NavigationMapView @@ -32,80 +34,67 @@ NavigationMapEditor.prototype.createControls = function() { self.map.on('pm:create', function(e) { var geojson = e.layer.toGeoJSON(); self.blueprint[e.layer._leaflet_id] = geojson; - self.renderRow(e.layer, geojson); + self.attachEditorEvents(e.layer); + self.createAreaCallback(e.layer._leaflet_id, e.layer, self); }); self.map.on('pm:remove', function(e) { delete self.blueprint[e.layer._leaflet_id]; - document.getElementById(self.rowId(e.layer._leaflet_id)).remove(); + self.removeAreaCallback(e.layer._leaflet_id, e.layer, self); }); }; +NavigationMapEditor.prototype.editing = function() { + var pm = this.map.pm; + return pm.globalRemovalEnabled() || pm.globalDragModeEnabled() || pm.globalEditEnabled(); +}; + NavigationMapView.prototype.createAreas = function() { var self = this; self.forEachBlueprint(function(id, geoarea) { new L.GeoJSON(geoarea, { onEachFeature: function(feature, layer) { layer._leaflet_id = id; - layer.on('mouseover', function(e) { - e.target.getElement().classList.add('selected') - document.getElementById(self.rowId(e.target._leaflet_id)).classList.add('selected'); - }); - - layer.on('mouseout', function(e) { - e.target.getElement().classList.remove('selected') - document.getElementById(self.rowId(e.target._leaflet_id)).classList.remove('selected'); - }); - - layer.on('pm:edit', function(e) { - self.blueprint[e.target._leaflet_id] = e.target.toGeoJSON(); - }); - - layer.on('click', function(e) { - self.clickAreaCallback(e.target._leaflet_id, e.target, self); - }); - - self.renderRow(layer, feature); + self.attachEditorEvents(layer); } }).addTo(self.map); }); }; -NavigationMapEditor.prototype.renderRow = function (layer, feature) { +// register callback to handle area edits,removals and creations +NavigationMapView.prototype.onCreateArea = function(callback) { + this.createAreaCallback = callback; +}; +NavigationMapView.prototype.onEditArea = function(callback) { + this.editAreaCallback = callback; +}; +NavigationMapView.prototype.onRemoveArea = function(callback) { + this.removeCreateCallback = callback; +}; + +NavigationMapEditor.prototype.attachEditorEvents = function (layer) { var self = this; - var tbody = self.table_object.getElementsByTagName('tbody')[0]; - var tr = this.rowTemplate(layer._leaflet_id, feature); - tr.addEventListener("mouseover", function() { - layer.getElement().classList.add('selected') + layer.on('mouseover', function(e) { + e.target.getElement().classList.add('selected') }); - tr.addEventListener("mouseout", function() { - layer.getElement().classList.remove('selected') + layer.on('mouseout', function(e) { + e.target.getElement().classList.remove('selected') }); - tbody.appendChild(tr); -}; - -NavigationMapEditor.prototype.rowTemplate = function (area, feature) { - var link = feature.properties && feature.properties.link || '#'; - var tr = document.createElement('tr'); - tr.id = this.rowId(area); - tr.innerHTML = ' ' + area +'' - + ' '; - return tr; -}; + layer.on('pm:edit', function(e) { + self.blueprint[e.target._leaflet_id] = e.target.toGeoJSON(); + self.editAreaCallback(e.target._leaflet_id, e.target, self); + }); -NavigationMapEditor.prototype.rowId = function (id) { - return `map-editor-${this.id}-tr-${id}`; + layer.on('click', function(e) { + if(!self.editing()) { + self.clickAreaCallback(e.target._leaflet_id, e.target, self); + } + }); }; NavigationMapEditor.prototype.getBlueprint = function () { - var self = this; - self.forEachBlueprint(function(id, geoarea) { - var link = document.getElementById(self.rowId(id) + "-link"); - geoarea.properties = geoarea && geoarea.properties || {link: '#'} - if(link) geoarea.properties.link = link.value; - }); - return self.blueprint; + return this.blueprint; }; diff --git a/app/assets/javascripts/decidim/navigation_maps/admin/navigation_maps.js b/app/assets/javascripts/decidim/navigation_maps/admin/navigation_maps.js index 8e9e80c..ecb28e6 100644 --- a/app/assets/javascripts/decidim/navigation_maps/admin/navigation_maps.js +++ b/app/assets/javascripts/decidim/navigation_maps/admin/navigation_maps.js @@ -1,7 +1,5 @@ // Place all the behaviors and hooks related to the matching controller here. // All this logic will automatically be available in application.js. -//= require leaflet -//= require leaflet-geoman.min //= require jquery.form //= require decidim/navigation_maps/admin/map_editor //= require_self @@ -18,18 +16,32 @@ $(function() { var $tabs = $('#navigation_maps-tabs'); var $accordion = $('.navigation_maps.admin .accordion'); var editors = {}; + var new_areas = {}; $maps.each(function() { var id = $(this).data('id'); var table = document.getElementById("navigation_maps-table-" + id); editors[id] = new NavigationMapEditor(this, table); + editors[id].onCreateArea(function(area_id, area, obj) { + new_areas[area_id] = true; + }); + editors[id].onClickArea(function(area_id, area, obj) { $modal.find('.modal-content').html(''); $modal.addClass('loading').foundation('open'); $callout.hide(); $callout.removeClass('alert success'); - $modal.find('.modal-content').load(`/admin/navigation_maps/blueprints/${id}/areas/${area_id}`, function() { + // "new" form insted of editing + var rel = new_areas[area_id] ? 'new' : area_id; + $modal.find('.modal-content').load(`/admin/navigation_maps/blueprints/${id}/areas/${rel}`, function() { + var $input1 = $modal.find('input[name="blueprint_area[area_id]"]'); + var $input2 = $modal.find('input[name="blueprint_area[area_type]"]'); + var $input3 = $modal.find('input[name="blueprint_area[area]"]'); + var a = area.toGeoJSON(); $modal.removeClass('loading'); + if($input1.length) $input1.val(area_id); + if($input2.length) $input2.val(a.type); + if($input3.length) $input3.val(JSON.stringify(a)); }); }); }); @@ -41,13 +53,14 @@ $(function() { }); document.body.addEventListener('ajax:success', function(responseText) { - console.log(responseText); + if(new_areas[responseText.detail[0].area]) { + delete new_areas[responseText.detail[0].area] + } $callout.contents('p').html(responseText.detail[0].message); $callout.addClass('success'); }); document.body.addEventListener('ajax:complete', function(xhr, event) { - console.log(event, xhr) $callout.show(); $modal.foundation('close'); }) diff --git a/app/assets/javascripts/decidim/navigation_maps/map_view.js b/app/assets/javascripts/decidim/navigation_maps/map_view.js index f65c4c9..5ee254b 100644 --- a/app/assets/javascripts/decidim/navigation_maps/map_view.js +++ b/app/assets/javascripts/decidim/navigation_maps/map_view.js @@ -1,3 +1,5 @@ +//= require leaflet +//= require leaflet-geoman.min // Creates a map view function NavigationMapView(map_object, callback) { diff --git a/app/assets/javascripts/decidim/navigation_maps/navigation_maps.js b/app/assets/javascripts/decidim/navigation_maps/navigation_maps.js index d460a47..76aa488 100644 --- a/app/assets/javascripts/decidim/navigation_maps/navigation_maps.js +++ b/app/assets/javascripts/decidim/navigation_maps/navigation_maps.js @@ -1,7 +1,5 @@ // Place all the behaviors and hooks related to the matching controller here. // All this logic will automatically be available in application.js. -//= require leaflet -//= require leaflet-geoman.min //= require decidim/navigation_maps/map_view //= require_self diff --git a/app/assets/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss b/app/assets/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss index 9969ba6..75cfada 100644 --- a/app/assets/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss +++ b/app/assets/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss @@ -74,14 +74,6 @@ border-top: 1px solid $dark-gray; padding: 1em 1em 0; } - tbody > tr { - &.selected { - background-color: "rgba(#{$leaflet-background-color}, 0.5)" !important; - } - &:hover { - background-color: "rgba(#{$leaflet-background-color}, 0.5)" !important; - } - } .leaflet-interactive { fill: "rgba(#{$leaflet-background-color}, 1)"; color: "rgba(#{$leaflet-background-color}, 1)"; diff --git a/app/commands/decidim/navigation_maps/save_area.rb b/app/commands/decidim/navigation_maps/save_area.rb index f84ffcc..b3dd459 100644 --- a/app/commands/decidim/navigation_maps/save_area.rb +++ b/app/commands/decidim/navigation_maps/save_area.rb @@ -24,21 +24,22 @@ def call update_area save_area! - broadcast(:ok) + broadcast(:ok, @area) end private - attr_reader :form + attr_reader :form, :current_blueprint def initialize_area - @area = BlueprintArea.find_or_initialize_by(id: form.id) do |area| - area.blueprint = form.current_blueprint - end + @area = BlueprintArea.find_or_initialize_by(area_id: form.area_id, blueprint: @form.context.current_blueprint); end def update_area @area.link = form.link + @area.area_id = form.area_id if form.area_id + @area.area = form.area if form.area + @area.area_type = form.area_type if form.area_type end def save_area! diff --git a/app/commands/decidim/navigation_maps/save_blueprints.rb b/app/commands/decidim/navigation_maps/save_blueprints.rb index 03f6d3e..e224b10 100644 --- a/app/commands/decidim/navigation_maps/save_blueprints.rb +++ b/app/commands/decidim/navigation_maps/save_blueprints.rb @@ -61,11 +61,12 @@ def delete_areas end def create_areas(blueprint) - blueprint.each do |_key, area| + blueprint.each do |key, area| BlueprintArea.create!( blueprint: @blueprint, area: area[:geometry], - area_type: area[:type] + area_type: area[:type], + area_id: key ) end end diff --git a/app/controllers/decidim/navigation_maps/admin/areas_controller.rb b/app/controllers/decidim/navigation_maps/admin/areas_controller.rb index e381d70..4385224 100644 --- a/app/controllers/decidim/navigation_maps/admin/areas_controller.rb +++ b/app/controllers/decidim/navigation_maps/admin/areas_controller.rb @@ -14,18 +14,35 @@ def index render json: blueprint.areas end - def new; end + def new + @form = form(AreaForm).instance(current_blueprint: blueprint) + end + + def create + parse_areas + @form = form(AreaForm).from_params(params, current_blueprint: blueprint) + + SaveArea.call(@form) do + on(:ok) do |area| + render json: { message: I18n.t("navigation_maps.admin.areas.create.success", scope: "decidim"), area: area.area_id, blueprint: area.blueprint.id } + end + + on(:invalid) do |message| + render json: { message: I18n.t("navigation_maps.admin.areas.create.error", scope: "decidim"), error: message }, status: :unprocessable_entity + end + end + end def show - @form = AreaForm.from_model(area) + @form = form(AreaForm).from_model(area) end def update @form = form(AreaForm).from_params(params, current_blueprint: blueprint) SaveArea.call(@form) do - on(:ok) do |_message| - render json: { message: I18n.t("navigation_maps.admin.areas.update.success", scope: "decidim") } + on(:ok) do |area| + render json: { message: I18n.t("navigation_maps.admin.areas.update.success", scope: "decidim"), area: area.area_id, blueprint: area.blueprint.id } end on(:invalid) do |message| @@ -36,12 +53,21 @@ def update private + def parse_areas + return unless params[:blueprint_area] + return unless params[:blueprint_area][:area].present? + + feature = JSON.parse params[:blueprint_area][:area] + params[:blueprint_area][:area] = feature["geometry"] if feature["geometry"] + params[:blueprint_area][:area_type] = feature["type"] if feature["type"] + end + def blueprint @blueprint ||= Blueprint.find(params[:blueprint_id]) end def area - @area ||= BlueprintArea.find(params[:id]) + @area ||= BlueprintArea.find_by(area_id: params[:area_id], blueprint: blueprint) end end end diff --git a/app/forms/decidim/navigation_maps/area_form.rb b/app/forms/decidim/navigation_maps/area_form.rb index e6233bc..ec614ff 100644 --- a/app/forms/decidim/navigation_maps/area_form.rb +++ b/app/forms/decidim/navigation_maps/area_form.rb @@ -10,6 +10,8 @@ class AreaForm < Decidim::Form mimic :blueprint_area attribute :area, Object + attribute :area_type, String + attribute :area_id, String attribute :link, String translatable_attribute :title, String translatable_attribute :description, String diff --git a/app/models/decidim/navigation_maps/blueprint.rb b/app/models/decidim/navigation_maps/blueprint.rb index debd1a6..721c036 100644 --- a/app/models/decidim/navigation_maps/blueprint.rb +++ b/app/models/decidim/navigation_maps/blueprint.rb @@ -20,12 +20,7 @@ class Blueprint < ApplicationRecord mount_uploader :image, Decidim::NavigationMaps::BlueprintUploader def blueprint - areas.map do |area| - [area.id.to_s, { - type: area.area_type, - geometry: area.area - }] - end.to_h + areas.map { |area| [area.area_id.to_s, area.to_geoson] }.to_h end end end diff --git a/app/models/decidim/navigation_maps/blueprint_area.rb b/app/models/decidim/navigation_maps/blueprint_area.rb index 31eb995..bbb7694 100644 --- a/app/models/decidim/navigation_maps/blueprint_area.rb +++ b/app/models/decidim/navigation_maps/blueprint_area.rb @@ -9,6 +9,16 @@ class BlueprintArea < ApplicationRecord belongs_to :blueprint, foreign_key: :decidim_navigation_maps_blueprint_id, class_name: "Decidim::NavigationMaps::Blueprint" validates :blueprint, presence: true + + def to_geoson + { + type: area_type, + geometry: area, + properties: { + link: link + } + } + end end end end diff --git a/app/views/decidim/navigation_maps/admin/areas/new.html.erb b/app/views/decidim/navigation_maps/admin/areas/new.html.erb index 3e75765..669e5b9 100644 --- a/app/views/decidim/navigation_maps/admin/areas/new.html.erb +++ b/app/views/decidim/navigation_maps/admin/areas/new.html.erb @@ -1 +1,17 @@ -new +<%= decidim_form_for(@form, url: blueprint_areas_path, remote: true) do |f| %> +
+
+

<%= t ".area" %>

+
+
+ <%= render partial: "form", object: f %> + <%= f.hidden_field :area %> + <%= f.hidden_field :area_id %> + <%= f.hidden_field :area_type %> +
+
+
+ <%= f.submit t(".save") %> + +
+<% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index e2cb3cf..5fa59ee 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -7,6 +7,10 @@ en: navigation_maps: admin: areas: + new: + area: New area details + save: Save + cancel: Cancel show: area: Area details save: Save @@ -14,6 +18,9 @@ en: update: success: Area saved successfully error: An error ocurred while saving the area + create: + success: Area created successfully + error: An error ocurred while creating the area content_blocks: name: Navigation Maps navigation_map_settings_form: diff --git a/db/migrate/20191126154019_add_area_id_to_decidim_navigation_maps_blueprint_areas.rb b/db/migrate/20191126154019_add_area_id_to_decidim_navigation_maps_blueprint_areas.rb new file mode 100644 index 0000000..b5dbe16 --- /dev/null +++ b/db/migrate/20191126154019_add_area_id_to_decidim_navigation_maps_blueprint_areas.rb @@ -0,0 +1,14 @@ +class AddAreaIdToDecidimNavigationMapsBlueprintAreas < ActiveRecord::Migration[5.2] + class Area < ApplicationRecord + self.table_name = "decidim_navigation_maps_blueprint_areas" + end + + def change + add_column :decidim_navigation_maps_blueprint_areas, :area_id, :string + + Area.find_each do |area| + area.area_id = area.id + area.save! + end + end +end diff --git a/lib/decidim/navigation_maps/admin_engine.rb b/lib/decidim/navigation_maps/admin_engine.rb index 3b1fb75..1f9bdaf 100644 --- a/lib/decidim/navigation_maps/admin_engine.rb +++ b/lib/decidim/navigation_maps/admin_engine.rb @@ -12,7 +12,7 @@ class AdminEngine < ::Rails::Engine routes do # Add admin engine routes here resources :blueprints, only: [:index, :show, :create] do - resources :areas + resources :areas, param: :area_id end end diff --git a/spec/commands/save_area_spec.rb b/spec/commands/save_area_spec.rb index 6ee744c..66e25fc 100644 --- a/spec/commands/save_area_spec.rb +++ b/spec/commands/save_area_spec.rb @@ -41,8 +41,8 @@ module Decidim::NavigationMaps end context "when id exists" do - let!(:area) { create(:blueprint_area, blueprint: blueprint) } - let(:id) { area.id } + let!(:blueprint_area) { create(:blueprint_area, blueprint: blueprint) } + let(:id) { blueprint_area.id } it "broadcasts ok" do expect { subject.call }.to broadcast(:ok) @@ -52,5 +52,18 @@ module Decidim::NavigationMaps expect { subject.call }.to change(BlueprintArea, :count).by(0) end end + + context "when id does not exist" do + let(:blueprint_area) { build(:blueprint_area, id: id, blueprint: blueprint) } + let(:id) { 11101 } + + it "broadcasts ok" do + expect { subject.call }.to broadcast(:ok) + end + + it "creates the area" do + expect { subject.call }.to change(BlueprintArea, :count).by(1) + end + end end end diff --git a/spec/controllers/decidim/area_controller_spec.rb b/spec/controllers/decidim/area_controller_spec.rb new file mode 100644 index 0000000..2fbdbd8 --- /dev/null +++ b/spec/controllers/decidim/area_controller_spec.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim::NavigationMaps::Admin + describe AreasController, type: :controller do + routes { Decidim::NavigationMaps::AdminEngine.routes } + + let(:organization) { create(:organization) } + let(:user) { create(:user, :confirmed, :admin, organization: organization) } + let(:blueprint) { create(:blueprint, organization: organization) } + + let(:params) do + { + blueprint_area: { + area: data, + id: id, + title: title, + description: title, + link: link, + current_blueprint: blueprint + } + } + end + let(:data) do + { x: 0.5, y: 0.6 } + end + let(:title) { Decidim::Faker::Localized.sentence(2) } + let(:description) { Decidim::Faker::Localized.paragraph } + let(:id) { nil } + let(:link) { "#link" } + + before do + request.env["decidim.current_organization"] = user.organization + sign_in user, scope: :user + end + + describe "GET #index" do + it "returns http success" do + get :index, params: { blueprint_id: blueprint.id } + expect(response).to have_http_status(:success) + expect(response.body).to eq("[]") + end + end + + describe "GET #show" do + context "when area exists" do + let!(:area) { create(:blueprint_area, blueprint: blueprint) } + + it "returns http success" do + get :show, params: { blueprint_id: blueprint.id, id: area.id } + expect(response).to have_http_status(:success) + end + end + context "when area does not exist" do + it "redirects to new" do + get :show, params: { blueprint_id: blueprint.id, id: 1111 } + expect(response).to have_http_status(:success) + end + end + end + + describe "POST #update" do + let!(:area) { create(:blueprint_area, blueprint: blueprint) } + + it "returns http success" do + post :update, params: { blueprint_id: blueprint.id, id: area.id } + expect(response).to have_http_status(:success) + end + end + end +end diff --git a/spec/controllers/decidim/blueprint_controller_spec.rb b/spec/controllers/decidim/blueprint_controller_spec.rb index a1639e6..9a567de 100644 --- a/spec/controllers/decidim/blueprint_controller_spec.rb +++ b/spec/controllers/decidim/blueprint_controller_spec.rb @@ -34,7 +34,7 @@ module Decidim::NavigationMaps::Admin end end - describe "GET #create" do + describe "POST #create" do it "returns http success" do post :create expect(response).to have_http_status(:success) From 76113570578b0e76553c3ac9f35a0bf459355fb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Wed, 27 Nov 2019 10:36:09 +0100 Subject: [PATCH 7/8] test fixes --- Gemfile.lock | 2 +- .../navigation_map_settings_form/show.erb | 2 -- .../decidim/navigation_maps/save_area.rb | 2 +- .../navigation_maps/admin/areas_controller.rb | 2 +- config/locales/en.yml | 28 +++++++++--------- ...decidim_navigation_maps_blueprint_areas.rb | 22 -------------- ...decidim_navigation_maps_blueprint_areas.rb | 2 ++ lib/decidim/navigation_maps/test/factories.rb | 11 +++++-- spec/commands/save_area_spec.rb | 20 ++++++++----- .../{decidim => }/area_controller_spec.rb | 9 +++--- .../blueprint_controller_spec.rb | 4 +-- spec/model/blueprint_area_spec.rb | 9 ++++-- spec/model/blueprint_spec.rb | 29 +++++++++++++------ 13 files changed, 73 insertions(+), 69 deletions(-) rename spec/controllers/{decidim => }/area_controller_spec.rb (87%) rename spec/controllers/{decidim => }/blueprint_controller_spec.rb (96%) diff --git a/Gemfile.lock b/Gemfile.lock index b7bc7c5..b728126 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -758,7 +758,7 @@ DEPENDENCIES web-console (~> 3.5) RUBY VERSION - ruby 2.6.5p114 + ruby 2.6.3p62 BUNDLED WITH 2.0.2 diff --git a/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/show.erb b/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/show.erb index d060506..f9b2c5d 100644 --- a/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/show.erb +++ b/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/show.erb @@ -15,8 +15,6 @@ <%= render partial: "tabs", locals: { tabs: blueprints } %> <%= render partial: "tabs_content", locals: { tabs: blueprints } %> - -
diff --git a/app/commands/decidim/navigation_maps/save_area.rb b/app/commands/decidim/navigation_maps/save_area.rb index b3dd459..e6f97b5 100644 --- a/app/commands/decidim/navigation_maps/save_area.rb +++ b/app/commands/decidim/navigation_maps/save_area.rb @@ -32,7 +32,7 @@ def call attr_reader :form, :current_blueprint def initialize_area - @area = BlueprintArea.find_or_initialize_by(area_id: form.area_id, blueprint: @form.context.current_blueprint); + @area = BlueprintArea.find_or_initialize_by(area_id: form.area_id, blueprint: @form.context.current_blueprint) end def update_area diff --git a/app/controllers/decidim/navigation_maps/admin/areas_controller.rb b/app/controllers/decidim/navigation_maps/admin/areas_controller.rb index 4385224..8d2004d 100644 --- a/app/controllers/decidim/navigation_maps/admin/areas_controller.rb +++ b/app/controllers/decidim/navigation_maps/admin/areas_controller.rb @@ -55,7 +55,7 @@ def update def parse_areas return unless params[:blueprint_area] - return unless params[:blueprint_area][:area].present? + return if params[:blueprint_area][:area].blank? feature = JSON.parse params[:blueprint_area][:area] params[:blueprint_area][:area] = feature["geometry"] if feature["geometry"] diff --git a/config/locales/en.yml b/config/locales/en.yml index 5fa59ee..9bf2d82 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -7,35 +7,35 @@ en: navigation_maps: admin: areas: + create: + error: An error ocurred while creating the area + success: Area created successfully new: area: New area details - save: Save cancel: Cancel + save: Save show: area: Area details - save: Save cancel: Cancel + save: Save update: - success: Area saved successfully error: An error ocurred while saving the area - create: - success: Area created successfully - error: An error ocurred while creating the area + success: Area saved successfully content_blocks: name: Navigation Maps navigation_map_settings_form: + add: Add blueprint_image: Blueprint image - image_missing: Please add a blueprint image to start - upload_image: Upload image - id: Id - type: Type - link: Link - title: Title description: Description - add: Add - info: General info editor: Map Editor + id: Id + image_missing: Please add a blueprint image to start + info: General info + link: Link remove_blueprint: Delete this blueprint + title: Title + type: Type + upload_image: Upload image create: error: Error creating blueprint success: Blueprint created successfully diff --git a/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb b/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb index ec5b50c..f70a227 100644 --- a/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb +++ b/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb @@ -1,14 +1,6 @@ # frozen_string_literal: true class CreateDecidimNavigationMapsBlueprintAreas < ActiveRecord::Migration[5.2] - class Blueprint < ApplicationRecord - self.table_name = "decidim_navigation_maps_blueprints" - end - - class Area < ApplicationRecord - self.table_name = "decidim_navigation_maps_blueprint_areas" - end - def change create_table :decidim_navigation_maps_blueprint_areas do |t| t.jsonb :area @@ -21,20 +13,6 @@ def change t.timestamps end - # Search areas and create distributed entries - Blueprint.find_each do |blueprint| - next unless blueprint.blueprint - - blueprint.blueprint.each do |_key, area| - Area.create!( - area: area["geometry"], - decidim_navigation_maps_blueprint_id: blueprint.id, - area_type: area["type"], - url: area["properties"]["link"] - ) - end - end - remove_column :decidim_navigation_maps_blueprints, :blueprint, :jsonb end end diff --git a/db/migrate/20191126154019_add_area_id_to_decidim_navigation_maps_blueprint_areas.rb b/db/migrate/20191126154019_add_area_id_to_decidim_navigation_maps_blueprint_areas.rb index b5dbe16..b914529 100644 --- a/db/migrate/20191126154019_add_area_id_to_decidim_navigation_maps_blueprint_areas.rb +++ b/db/migrate/20191126154019_add_area_id_to_decidim_navigation_maps_blueprint_areas.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddAreaIdToDecidimNavigationMapsBlueprintAreas < ActiveRecord::Migration[5.2] class Area < ApplicationRecord self.table_name = "decidim_navigation_maps_blueprint_areas" diff --git a/lib/decidim/navigation_maps/test/factories.rb b/lib/decidim/navigation_maps/test/factories.rb index 67dc541..f501a6f 100644 --- a/lib/decidim/navigation_maps/test/factories.rb +++ b/lib/decidim/navigation_maps/test/factories.rb @@ -12,9 +12,16 @@ factory :blueprint_area, class: Decidim::NavigationMaps::BlueprintArea do blueprint { create(:blueprint) } - area { { x: 1, y: 1 } } + area do + { + "x" => 1, + "y" => 1 + } + end area_type { "Feature" } - link { "#" } + area_id { "1" } + link { "#link" } + link_type { "link" } title { Decidim::Faker::Localized.word } description { generate_localized_title } end diff --git a/spec/commands/save_area_spec.rb b/spec/commands/save_area_spec.rb index 66e25fc..0f94c56 100644 --- a/spec/commands/save_area_spec.rb +++ b/spec/commands/save_area_spec.rb @@ -8,22 +8,26 @@ module Decidim::NavigationMaps let(:blueprint) { create :blueprint } let(:form) do - double( - AreaForm, + AreaForm + .from_params(attributes) + .with_context(current_blueprint: blueprint) + end + let(:attributes) do + { area: data, - id: id, + area_id: area_id, title: title, description: title, link: link, current_blueprint: blueprint - ) + } end let(:data) do { x: 0.5, y: 0.6 } end let(:title) { Decidim::Faker::Localized.sentence(2) } let(:description) { Decidim::Faker::Localized.paragraph } - let(:id) { nil } + let(:area_id) { nil } let(:link) { "#link" } before do @@ -42,20 +46,20 @@ module Decidim::NavigationMaps context "when id exists" do let!(:blueprint_area) { create(:blueprint_area, blueprint: blueprint) } - let(:id) { blueprint_area.id } + let(:area_id) { blueprint_area.area_id } it "broadcasts ok" do expect { subject.call }.to broadcast(:ok) end - it "creates the area" do + it "updates the area" do expect { subject.call }.to change(BlueprintArea, :count).by(0) end end context "when id does not exist" do let(:blueprint_area) { build(:blueprint_area, id: id, blueprint: blueprint) } - let(:id) { 11101 } + let(:id) { 11_101 } it "broadcasts ok" do expect { subject.call }.to broadcast(:ok) diff --git a/spec/controllers/decidim/area_controller_spec.rb b/spec/controllers/area_controller_spec.rb similarity index 87% rename from spec/controllers/decidim/area_controller_spec.rb rename to spec/controllers/area_controller_spec.rb index 2fbdbd8..6ad327b 100644 --- a/spec/controllers/decidim/area_controller_spec.rb +++ b/spec/controllers/area_controller_spec.rb @@ -10,7 +10,7 @@ module Decidim::NavigationMaps::Admin let(:user) { create(:user, :confirmed, :admin, organization: organization) } let(:blueprint) { create(:blueprint, organization: organization) } - let(:params) do + let(:attributes) do { blueprint_area: { area: data, @@ -48,13 +48,14 @@ module Decidim::NavigationMaps::Admin let!(:area) { create(:blueprint_area, blueprint: blueprint) } it "returns http success" do - get :show, params: { blueprint_id: blueprint.id, id: area.id } + get :show, params: { blueprint_id: blueprint.id, area_id: area.area_id } expect(response).to have_http_status(:success) end end + context "when area does not exist" do it "redirects to new" do - get :show, params: { blueprint_id: blueprint.id, id: 1111 } + get :show, params: { blueprint_id: blueprint.id, area_id: 1111 } expect(response).to have_http_status(:success) end end @@ -64,7 +65,7 @@ module Decidim::NavigationMaps::Admin let!(:area) { create(:blueprint_area, blueprint: blueprint) } it "returns http success" do - post :update, params: { blueprint_id: blueprint.id, id: area.id } + post :update, params: { blueprint_id: blueprint.id, area_id: area.area_id } expect(response).to have_http_status(:success) end end diff --git a/spec/controllers/decidim/blueprint_controller_spec.rb b/spec/controllers/blueprint_controller_spec.rb similarity index 96% rename from spec/controllers/decidim/blueprint_controller_spec.rb rename to spec/controllers/blueprint_controller_spec.rb index 9a567de..c1e381a 100644 --- a/spec/controllers/decidim/blueprint_controller_spec.rb +++ b/spec/controllers/blueprint_controller_spec.rb @@ -7,9 +7,7 @@ module Decidim::NavigationMaps::Admin routes { Decidim::NavigationMaps::AdminEngine.routes } let(:user) { create(:user, :confirmed, :admin, organization: organization) } - let(:organization) do - create(:organization) - end + let(:organization) { create(:organization) } let(:params) do { blueprints: { diff --git a/spec/model/blueprint_area_spec.rb b/spec/model/blueprint_area_spec.rb index 24eb36b..d5f622c 100644 --- a/spec/model/blueprint_area_spec.rb +++ b/spec/model/blueprint_area_spec.rb @@ -9,13 +9,14 @@ module NavigationMaps let(:organization) { create(:organization) } let(:blueprint) { create(:blueprint, organization: organization) } - let(:blueprint_area) { build(:blueprint_area, title: title, description: description, link: link, area: area, blueprint: blueprint) } + let(:blueprint_area) { build(:blueprint_area, blueprint: blueprint) } let(:area) do { "x" => "coord x", "y" => "coord y" } end + let(:area_id) { "101" } let(:title) { Decidim::Faker::Localized.sentence(2) } let(:description) { Decidim::Faker::Localized.paragraph } let(:link) { "#link" } @@ -29,18 +30,21 @@ module NavigationMaps # TODO: validate json area context "when all fields are specified" do + let!(:blueprint_area) { create(:blueprint_area, title: title, description: description, link: link, area: area, area_id: area_id, blueprint: blueprint) } + it "saves data correctly" do subject.save subject.reload expect(subject.title).to eq(title) expect(subject.description).to eq(description) expect(subject.link).to eq(link) + expect(subject.area_id).to eq(area_id) expect(subject.area).to eq(area) end end context "when no area" do - let!(:blueprint_area) { create(:blueprint_area, title: title, description: description, link: link, area: area, blueprint: blueprint) } + let!(:blueprint_area) { create(:blueprint_area, area: area, area_id: area_id, blueprint: blueprint) } it "save data without area" do a = BlueprintArea.find(blueprint_area.id) @@ -52,6 +56,7 @@ module NavigationMaps expect(a.title).to eq(title) expect(a.description).to eq(description) expect(a.link).to eq(link) + expect(a.area_id).to eq(area_id) expect(a.area).to eq(area) end end diff --git a/spec/model/blueprint_spec.rb b/spec/model/blueprint_spec.rb index 9a17c90..5002e23 100644 --- a/spec/model/blueprint_spec.rb +++ b/spec/model/blueprint_spec.rb @@ -38,24 +38,35 @@ module NavigationMaps context "when areas are defined" do let!(:blueprint) { create(:blueprint, organization: organization) } - let!(:area1) { create(:blueprint_area, area: data1, blueprint: blueprint) } - let!(:area2) { create(:blueprint_area, area: data2, blueprint: blueprint) } + let!(:area1) { create(:blueprint_area, area: data, area_id: "101", link: "#link1", blueprint: blueprint) } + let!(:area2) { create(:blueprint_area, area: data, area_id: "102", link: "#link1", blueprint: blueprint) } let(:blueprint_object) do { - area1.id.to_s => { + "101" => { type: "Feature", - geometry: data1 + geometry: data, + properties: properties }, - area2.id.to_s => { + "102" => { type: "Feature", - geometry: data2 + geometry: data, + properties: properties } } end - let(:area3) { create(:blueprint_area, area: data2) } - let(:data1) { { "x" => "coord x", "y" => "coord y" } } - let(:data2) { { "x" => "coord x", "y" => "coord y" } } + let(:area3) { create(:blueprint_area, area: data) } + let(:data) do + { + "x" => "coord x", + "y" => "coord y" + } + end + let(:properties) do + { + link: "#link1" + } + end it { is_expected.to be_valid } From 276bd67dc0253215d72892a1ae5809445358ab11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Wed, 27 Nov 2019 12:16:37 +0100 Subject: [PATCH 8/8] fix tests --- spec/model/blueprint_area_spec.rb | 9 +++++++-- spec/model/blueprint_spec.rb | 25 +++++++++++++++---------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/spec/model/blueprint_area_spec.rb b/spec/model/blueprint_area_spec.rb index d5f622c..0afbbe2 100644 --- a/spec/model/blueprint_area_spec.rb +++ b/spec/model/blueprint_area_spec.rb @@ -30,9 +30,11 @@ module NavigationMaps # TODO: validate json area context "when all fields are specified" do - let!(:blueprint_area) { create(:blueprint_area, title: title, description: description, link: link, area: area, area_id: area_id, blueprint: blueprint) } + let(:blueprint_area) { create(:blueprint_area, title: title, description: description, link: link, blueprint: blueprint) } it "saves data correctly" do + subject.area = area + subject.area_id = area_id subject.save subject.reload expect(subject.title).to eq(title) @@ -44,9 +46,12 @@ module NavigationMaps end context "when no area" do - let!(:blueprint_area) { create(:blueprint_area, area: area, area_id: area_id, blueprint: blueprint) } + let!(:blueprint_area) { create(:blueprint_area, blueprint: blueprint) } it "save data without area" do + subject.area = area + subject.area_id = area_id + subject.save a = BlueprintArea.find(blueprint_area.id) a.title = title a.description = description diff --git a/spec/model/blueprint_spec.rb b/spec/model/blueprint_spec.rb index 5002e23..4095078 100644 --- a/spec/model/blueprint_spec.rb +++ b/spec/model/blueprint_spec.rb @@ -38,35 +38,34 @@ module NavigationMaps context "when areas are defined" do let!(:blueprint) { create(:blueprint, organization: organization) } - let!(:area1) { create(:blueprint_area, area: data, area_id: "101", link: "#link1", blueprint: blueprint) } - let!(:area2) { create(:blueprint_area, area: data, area_id: "102", link: "#link1", blueprint: blueprint) } + let!(:area1) { create(:blueprint_area, link: "#link", blueprint: blueprint) } + let!(:area2) { create(:blueprint_area, link: "#another_link", blueprint: blueprint) } + let!(:area3) { create(:blueprint_area, area: data) } let(:blueprint_object) do { "101" => { type: "Feature", geometry: data, - properties: properties + properties: { + link: "#link" + } }, "102" => { type: "Feature", geometry: data, - properties: properties + properties: { + link: "#another_link" + } } } end - let(:area3) { create(:blueprint_area, area: data) } let(:data) do { "x" => "coord x", "y" => "coord y" } end - let(:properties) do - { - link: "#link1" - } - end it { is_expected.to be_valid } @@ -83,6 +82,12 @@ module NavigationMaps end it "compacts json areas in a single object" do + area1.area = data + area1.area_id = "101" + area1.save + area2.area = data + area2.area_id = "102" + area2.save expect(blueprint.blueprint).to eq(blueprint_object) end end