decidim-navigation_maps 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +22 -3
- data/Rakefile +8 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map/_tabs_content.erb +1 -1
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map/show.erb +2 -2
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map_cell.rb +5 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/_form.erb +4 -4
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/_tabs_content.erb +0 -1
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/show.erb +4 -2
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form_cell.rb +9 -0
- data/app/controllers/decidim/navigation_maps/admin/blueprints_controller.rb +1 -1
- data/app/jobs/decidim/navigation_maps/migrate_legacy_images_job.rb +32 -0
- data/app/models/decidim/navigation_maps/blueprint.rb +4 -3
- data/app/packs/entrypoints/decidim_admin_navigation_maps.js +4 -0
- data/app/packs/entrypoints/decidim_admin_navigation_maps.scss +1 -0
- data/app/packs/entrypoints/decidim_navigation_maps.js +7 -0
- data/app/packs/entrypoints/decidim_navigation_maps.scss +1 -0
- data/app/packs/src/decidim/navigation_maps/admin/map_editor.js +83 -0
- data/app/packs/src/decidim/navigation_maps/admin/navigation_maps.js +154 -0
- data/app/packs/src/decidim/navigation_maps/map_view.js +125 -0
- data/app/packs/src/decidim/navigation_maps/navigation_maps.js +43 -0
- data/app/{assets → packs}/stylesheets/decidim/navigation_maps/_variables.scss +0 -0
- data/app/{assets → packs}/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss +4 -4
- data/app/{assets → packs}/stylesheets/decidim/navigation_maps/navigation_maps.scss +1 -2
- data/app/uploaders/decidim/navigation_maps/blueprint_uploader.rb +4 -12
- data/app/uploaders/decidim/navigation_maps/cw/blueprint_uploader.rb +24 -0
- data/config/assets.rb +41 -0
- data/config/locales/cs.yml +1 -1
- data/db/seeds.rb +6 -5
- data/lib/decidim/navigation_maps/admin_engine.rb +0 -4
- data/lib/decidim/navigation_maps/engine.rb +4 -4
- data/lib/decidim/navigation_maps/navigation_map_cell_helpers.rb +1 -1
- data/lib/decidim/navigation_maps/version.rb +2 -2
- data/lib/decidim/navigation_maps.rb +0 -2
- data/lib/tasks/decidim_navigation_maps_webpacker_tasks.rake +58 -0
- data/lib/tasks/navigation_maps_active_storage_migration_tasks.rake +37 -0
- metadata +31 -27
- data/app/assets/config/admin/decidim_navigation_maps_manifest.css +0 -3
- data/app/assets/config/admin/decidim_navigation_maps_manifest.js +0 -3
- data/app/assets/config/decidim_navigation_maps_manifest.css +0 -3
- data/app/assets/config/decidim_navigation_maps_manifest.js +0 -1
- data/app/assets/images/decidim/navigation_maps/icon.svg +0 -1
- data/app/assets/javascripts/decidim/navigation_maps/admin/map_editor.js +0 -88
- data/app/assets/javascripts/decidim/navigation_maps/admin/navigation_maps.js +0 -143
- data/app/assets/javascripts/decidim/navigation_maps/map_view.js +0 -123
- data/app/assets/javascripts/decidim/navigation_maps/navigation_maps.js +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 555b93edb92b69f19e3cc10841179b04fb57502a13d347fe69132d01833f88d6
|
4
|
+
data.tar.gz: 76da0880561f5e1e5b1201a048d90c8a862194134f3e485c1d2d045401f61551
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d90681644ff2111df383e19b5e7e7568c97cc225aad75645dcd86369332e91d4ef0d0fcc0ea6413c7bcb83bab0239333fb926958d8a32e62df5e2b52bd7353d1
|
7
|
+
data.tar.gz: bbc246049572a74e697a0382bd084213cdff071149ea1c2ef1a93eae78da2d1ceeba110b394c16c9877b5c88ecd96fca0c674b1f72193b7b86b993a5707c6daf
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ homepage only).
|
|
24
24
|
Add this line to your application's Gemfile:
|
25
25
|
|
26
26
|
```ruby
|
27
|
-
gem "decidim-navigation_maps"
|
27
|
+
gem "decidim-navigation_maps"
|
28
28
|
```
|
29
29
|
|
30
30
|
And then execute (remember to repeat this if you are upgrading from version 1.1):
|
@@ -32,16 +32,35 @@ And then execute (remember to repeat this if you are upgrading from version 1.1)
|
|
32
32
|
```bash
|
33
33
|
bundle
|
34
34
|
bundle exec rails decidim_navigation_maps:install:migrations
|
35
|
+
bundle exec rails decidim_navigation_maps:webpacker:install
|
35
36
|
bundle exec rails db:migrate
|
36
37
|
```
|
37
38
|
|
39
|
+
> NOTE: the `decidim_notify:webpacker:install` is only necessary for Decidim versions starting at 0.25.
|
40
|
+
|
41
|
+
If you are upgrading from a version prior to 1.3, make sure that you migrate your existing images to Active Storae:
|
42
|
+
|
43
|
+
```
|
44
|
+
RAILS_ENV=production bin/rails navigation_maps:active_storage_migrations:migrate_from_carrierwave
|
45
|
+
```
|
46
|
+
|
47
|
+
Or check your migration status with:
|
48
|
+
```
|
49
|
+
RAILS_ENV=production bin/rails navigation_maps:active_storage_migrations:check_migration_from_carrierwave
|
50
|
+
```
|
51
|
+
|
52
|
+
The correct version of Navigation Maps should resolved automatically by the Bundler.
|
53
|
+
However you can force some specific version using `gem "decidim-navigation_maps", "~> 1.3.0"` in the Gemfile.
|
54
|
+
|
55
|
+
|
38
56
|
Depending on your Decidim version, choose the corresponding Plugin version to ensure compatibility:
|
39
57
|
|
40
58
|
| Navigation Maps version | Compatible Decidim versions |
|
41
59
|
|---|---|
|
42
|
-
| 1.
|
43
|
-
| 1.1.x | 0.22.x, 0.23.x |
|
60
|
+
| 1.3.x | 0.25.x, 0.26.x |
|
44
61
|
| 1.2.x | 0.24.x |
|
62
|
+
| 1.1.x | 0.22.x, 0.23.x |
|
63
|
+
| 1.0.x | 0.18.x - 0.21.x |
|
45
64
|
|
46
65
|
## Contributing
|
47
66
|
|
data/Rakefile
CHANGED
@@ -9,6 +9,12 @@ def install_module(path)
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
+
def override_webpacker_config_files(path)
|
13
|
+
Dir.chdir(path) do
|
14
|
+
system("bundle exec rake decidim_navigation_maps:webpacker:install")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
12
18
|
def seed_db(path)
|
13
19
|
Dir.chdir(path) do
|
14
20
|
system("bundle exec rake db:seed")
|
@@ -25,6 +31,7 @@ desc "Generates a dummy app for testing"
|
|
25
31
|
task test_app: "decidim:generate_external_test_app" do
|
26
32
|
ENV["RAILS_ENV"] = "test"
|
27
33
|
install_module("spec/decidim_dummy_app")
|
34
|
+
override_webpacker_config_files("spec/decidim_dummy_app")
|
28
35
|
end
|
29
36
|
|
30
37
|
desc "Generates a development app"
|
@@ -42,6 +49,7 @@ task :development_app do
|
|
42
49
|
end
|
43
50
|
|
44
51
|
install_module("development_app")
|
52
|
+
override_webpacker_config_files("development_app")
|
45
53
|
ENV["SKIP_MODULE_SEEDS"] = "1"
|
46
54
|
seed_db("development_app")
|
47
55
|
# manually seed navigation maps to ensure participatory process groups are created
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<div class="tabs-content admin" data-tabs-content="navigation_maps-tabs">
|
3
3
|
<% tabs.each_with_index do |item, index| %>
|
4
4
|
<div class="tabs-panel<%= " is-active" if index.zero? %>" id="map<%= index %>">
|
5
|
-
<%= content_tag(:div, "", id: "navigation_maps-map-#{item.id}", class: "map", style: "height: #{item.height}px", data: { id: item.id, image: item.image
|
5
|
+
<%= content_tag(:div, "", id: "navigation_maps-map-#{item.id}", class: "map", style: "height: #{item.height}px", data: { id: item.id, image: image_path(item.image), blueprint: item.blueprint }) %>
|
6
6
|
</div>
|
7
7
|
<% end %>
|
8
8
|
</div>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%=
|
1
|
+
<%= stylesheet_pack_tag "decidim_navigation_maps" %>
|
2
2
|
<%= render partial: "styles", locals: { blueprints: valid_blueprints } %>
|
3
3
|
|
4
4
|
<section<%= class_tag(section_classes) %>>
|
@@ -18,4 +18,4 @@
|
|
18
18
|
</section>
|
19
19
|
|
20
20
|
<%= render partial: "template" %>
|
21
|
-
<%=
|
21
|
+
<%= javascript_pack_tag "decidim_navigation_maps" %>
|
data/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/_form.erb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
<ul class="accordion" data-accordion>
|
2
|
-
<li class="accordion-item<%= " is-active" unless
|
2
|
+
<li class="accordion-item<%= " is-active" unless image?(form) %>" data-accordion-item>
|
3
3
|
<a href="#" class="accordion-title"><%= t("navigation_map_settings_form.info", scope: "decidim.navigation_maps.content_blocks") %></a>
|
4
4
|
|
5
5
|
<div class="accordion-content" data-tab-content>
|
@@ -9,7 +9,7 @@
|
|
9
9
|
|
10
10
|
<%= label_tag t("navigation_map_settings_form.blueprint_image", scope: "decidim.navigation_maps.content_blocks") %>
|
11
11
|
<div class="thumbnail">
|
12
|
-
<%= image_tag form.image
|
12
|
+
<%= image_tag image_path(form.image, variant: :thumbnail) if image?(form) %>
|
13
13
|
</div>
|
14
14
|
<%= file_field_tag "blueprints[#{form.ident}][image]", { id: "blueprints_#{form.ident}_image", label: t("navigation_map_settings_form.title", scope: "decidim.navigation_maps.content_blocks") } %>
|
15
15
|
|
@@ -25,12 +25,12 @@
|
|
25
25
|
</div>
|
26
26
|
</li>
|
27
27
|
|
28
|
-
<% if
|
28
|
+
<% if image?(form) %>
|
29
29
|
<li class="accordion-item is-active" data-accordion-item>
|
30
30
|
<a href="#" class="accordion-title"><%= t("navigation_map_settings_form.editor", scope: "decidim.navigation_maps.content_blocks") %></a>
|
31
31
|
<div class="accordion-content navigation_maps-content" data-tab-content>
|
32
32
|
|
33
|
-
<%= content_tag(:div, "", id: "navigation_maps-map-#{form.ident}", class: "map", data: { id: form.ident, image: form.image
|
33
|
+
<%= content_tag(:div, "", id: "navigation_maps-map-#{form.ident}", class: "map", data: { id: form.ident, image: image_path(form.image), blueprint: form.blueprint }) %>
|
34
34
|
|
35
35
|
</div>
|
36
36
|
</li>
|
@@ -33,5 +33,7 @@
|
|
33
33
|
</div>
|
34
34
|
|
35
35
|
<%= render partial: "modal" %>
|
36
|
-
|
37
|
-
<%=
|
36
|
+
<%# we need to rely on a CDN due a bug in webpacker that renders twice jquery if importing a plugin %>
|
37
|
+
<%= javascript_include_tag "https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.3.0/jquery.form.min.js", integrity: "sha384-qlmct0AOBiA2VPZkMY3+2WqkHtIQ9lSdAsAn5RUJD/3vA5MKDgSGcdmIv4ycVxyn", crossorigin: "anonymous" %>
|
38
|
+
<%= javascript_pack_tag "decidim_admin_navigation_maps" %>
|
39
|
+
<%= stylesheet_pack_tag "decidim_admin_navigation_maps" %>
|
@@ -26,6 +26,15 @@ module Decidim
|
|
26
26
|
def label
|
27
27
|
I18n.t("decidim.content_blocks.html.html_content")
|
28
28
|
end
|
29
|
+
|
30
|
+
def image?(frm)
|
31
|
+
frm.image.attached?
|
32
|
+
end
|
33
|
+
|
34
|
+
def image_path(image, options = {})
|
35
|
+
options.merge!({ only_path: true })
|
36
|
+
Rails.application.routes.url_helpers.rails_blob_url(image, options)
|
37
|
+
end
|
29
38
|
end
|
30
39
|
end
|
31
40
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module NavigationMaps
|
5
|
+
class MigrateLegacyImagesJob < ApplicationJob
|
6
|
+
queue_as :default
|
7
|
+
|
8
|
+
def perform(organization_id, mappings = [], logger = Rails.logger)
|
9
|
+
@organization_id = organization_id
|
10
|
+
@routes_mappings = mappings
|
11
|
+
@logger = logger
|
12
|
+
|
13
|
+
migrate_all!
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :routes_mappings, :logger
|
19
|
+
|
20
|
+
def migrate_all!
|
21
|
+
Decidim::CarrierWaveMigratorService.migrate_attachment!(
|
22
|
+
klass: Decidim::NavigationMaps::BluePrint,
|
23
|
+
cw_attribute: "image",
|
24
|
+
cw_uploader: Decidim::NavigationMaps::Cw::ImageUploader,
|
25
|
+
as_attribute: "image",
|
26
|
+
logger: @logger,
|
27
|
+
routes_mappings: routes_mappings
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -4,6 +4,8 @@ module Decidim
|
|
4
4
|
module NavigationMaps
|
5
5
|
# Abstract class from which all models in this engine inherit.
|
6
6
|
class Blueprint < ApplicationRecord
|
7
|
+
include Decidim::HasUploadValidations
|
8
|
+
|
7
9
|
self.table_name = "decidim_navigation_maps_blueprints"
|
8
10
|
|
9
11
|
attribute :height, :integer, default: 475
|
@@ -16,11 +18,10 @@ module Decidim
|
|
16
18
|
dependent: :destroy
|
17
19
|
|
18
20
|
validates :organization, presence: true
|
19
|
-
validates :image,
|
20
|
-
file_content_type: { allow: ["image/jpeg", "image/png", "image/svg+xml"] }
|
21
21
|
validates :height, numericality: { greater_than: 0 }
|
22
22
|
|
23
|
-
|
23
|
+
has_one_attached :image
|
24
|
+
validates_upload :image, uploader: Decidim::NavigationMaps::BlueprintUploader
|
24
25
|
|
25
26
|
def blueprint
|
26
27
|
areas.map { |area| [area.area_id.to_s, area.to_geoson] }.to_h
|
@@ -0,0 +1 @@
|
|
1
|
+
@import "stylesheets/decidim/navigation_maps/admin/navigation_maps";
|
@@ -0,0 +1 @@
|
|
1
|
+
@import "stylesheets/decidim/navigation_maps/navigation_maps";
|
@@ -0,0 +1,83 @@
|
|
1
|
+
// Creates a map
|
2
|
+
import NavigationMapView from "src/decidim/navigation_maps/map_view.js";
|
3
|
+
|
4
|
+
export default class NavigationMapEditor extends NavigationMapView {
|
5
|
+
constructor(map_object, table_object) {
|
6
|
+
// Call constructor of superclass to initialize superclass-derived members.
|
7
|
+
super(map_object, () => {
|
8
|
+
this.createControls();
|
9
|
+
if (this.blueprint) {
|
10
|
+
this.createAreas();
|
11
|
+
}
|
12
|
+
});
|
13
|
+
this.table_object = table_object;
|
14
|
+
this.createAreaCallback = function () {};
|
15
|
+
this.editAreaCallback = function () {};
|
16
|
+
this.removeAreaCallback = function () {};
|
17
|
+
}
|
18
|
+
|
19
|
+
createControls() {
|
20
|
+
this.map.pm.addControls({
|
21
|
+
position: "topleft",
|
22
|
+
drawCircle: false,
|
23
|
+
drawMarker: false,
|
24
|
+
drawCircleMarker: false,
|
25
|
+
drawPolyline: false,
|
26
|
+
cutPolygon: false
|
27
|
+
});
|
28
|
+
|
29
|
+
this.map.on("pm:create", (e) => {
|
30
|
+
let geojson = e.layer.toGeoJSON();
|
31
|
+
this.blueprint[e.layer._leaflet_id] = geojson;
|
32
|
+
this.attachEditorEvents(e.layer);
|
33
|
+
this.createAreaCallback(e.layer._leaflet_id, e.layer, this);
|
34
|
+
});
|
35
|
+
|
36
|
+
this.map.on("pm:remove", (e) => {
|
37
|
+
delete this.blueprint[e.layer._leaflet_id];
|
38
|
+
this.removeAreaCallback(e.layer._leaflet_id, e.layer, this);
|
39
|
+
});
|
40
|
+
};
|
41
|
+
|
42
|
+
editing() {
|
43
|
+
let pm = this.map.pm;
|
44
|
+
return pm.globalRemovalEnabled() || pm.globalDragModeEnabled() || pm.globalEditEnabled();
|
45
|
+
};
|
46
|
+
|
47
|
+
// register callback to handle area edits,removals and creations
|
48
|
+
onCreateArea(callback) {
|
49
|
+
this.createAreaCallback = callback;
|
50
|
+
};
|
51
|
+
onEditArea(callback) {
|
52
|
+
this.editAreaCallback = callback;
|
53
|
+
};
|
54
|
+
onRemoveArea(callback) {
|
55
|
+
this.removeCreateCallback = callback;
|
56
|
+
};
|
57
|
+
|
58
|
+
attachEditorEvents (layer) {
|
59
|
+
layer.on("mouseover", (e) => {
|
60
|
+
e.target.getElement().classList.add("selected")
|
61
|
+
});
|
62
|
+
|
63
|
+
layer.on("mouseout", (e) => {
|
64
|
+
e.target.getElement().classList.remove("selected")
|
65
|
+
});
|
66
|
+
|
67
|
+
layer.on("pm:edit", (e) => {
|
68
|
+
this.blueprint[e.target._leaflet_id] = e.target.toGeoJSON();
|
69
|
+
this.editAreaCallback(e.target._leaflet_id, e.target, this);
|
70
|
+
});
|
71
|
+
|
72
|
+
layer.on("click", (e) => {
|
73
|
+
if (!this.editing()) {
|
74
|
+
this.clickAreaCallback(e.target._leaflet_id, e.target, this);
|
75
|
+
}
|
76
|
+
});
|
77
|
+
};
|
78
|
+
|
79
|
+
getBlueprint () {
|
80
|
+
return this.blueprint;
|
81
|
+
};
|
82
|
+
|
83
|
+
}
|
@@ -0,0 +1,154 @@
|
|
1
|
+
// Place all the behaviors and hooks related to the matching controller here.
|
2
|
+
// All this logic will automatically be available in application.js.
|
3
|
+
// import "jquery-form"; // we use a CDN instead due a bug in webpacker
|
4
|
+
import NavigationMapEditor from "src/decidim/navigation_maps/admin/map_editor.js";
|
5
|
+
|
6
|
+
$(() => {
|
7
|
+
|
8
|
+
let $maps = $(".navigation_maps.admin .map");
|
9
|
+
let $progress = $(".navigation_maps.admin .progress");
|
10
|
+
let $bar = $(".navigation_maps.admin .progress-meter");
|
11
|
+
let $loading = $(".navigation_maps.admin .loading");
|
12
|
+
let $callout = $(".navigation_maps.admin .callout");
|
13
|
+
let $modal = $("#mapEditModal");
|
14
|
+
let $form = $("form");
|
15
|
+
let $tabs = $("#navigation_maps-tabs");
|
16
|
+
let $accordion = $(".navigation_maps.admin .accordion");
|
17
|
+
let editors = {};
|
18
|
+
let new_areas = {};
|
19
|
+
|
20
|
+
$maps.each((_i, el) => {
|
21
|
+
let id = $(el).data("id");
|
22
|
+
let table = document.getElementById(`navigation_maps-table-${id}`);
|
23
|
+
editors[id] = new NavigationMapEditor(el, table);
|
24
|
+
editors[id].onCreateArea((area_id) => {
|
25
|
+
new_areas[area_id] = true;
|
26
|
+
});
|
27
|
+
|
28
|
+
editors[id].onClickArea((area_id, area) => {
|
29
|
+
$modal.find(".modal-content").html("");
|
30
|
+
$modal.addClass("loading").foundation("open");
|
31
|
+
$callout.hide();
|
32
|
+
$callout.removeClass("alert success");
|
33
|
+
// "new" form insted of editing
|
34
|
+
let rel = new_areas[area_id]
|
35
|
+
? "new"
|
36
|
+
: area_id;
|
37
|
+
$modal.find(".modal-content").load(`/admin/navigation_maps/blueprints/${id}/areas/${rel}`, () => {
|
38
|
+
let $input1 = $modal.find('input[name="blueprint_area[area_id]"]');
|
39
|
+
let $input2 = $modal.find('input[name="blueprint_area[area_type]"]');
|
40
|
+
let $input3 = $modal.find('input[name="blueprint_area[area]"]');
|
41
|
+
let a = area.toGeoJSON();
|
42
|
+
$modal.removeClass("loading");
|
43
|
+
if ($input1.length) {
|
44
|
+
$input1.val(area_id);
|
45
|
+
}
|
46
|
+
if ($input2.length) {
|
47
|
+
$input2.val(a.type);
|
48
|
+
}
|
49
|
+
if ($input3.length) {
|
50
|
+
$input3.val(JSON.stringify(a));
|
51
|
+
}
|
52
|
+
$modal.find("ul[data-tabs=true]").each(() => {
|
53
|
+
new Foundation.Tabs($(el)); // eslint-disable-line
|
54
|
+
});
|
55
|
+
});
|
56
|
+
});
|
57
|
+
});
|
58
|
+
|
59
|
+
// Rails AJAX events
|
60
|
+
document.body.addEventListener("ajax:error", (responseText) => {
|
61
|
+
$callout.contents("p").html(`${responseText.detail[0].message}: <strong>${responseText.detail[0].error}</strong>`);
|
62
|
+
$callout.addClass("alert");
|
63
|
+
});
|
64
|
+
|
65
|
+
document.body.addEventListener("ajax:success", (responseText) => {
|
66
|
+
if (new_areas[responseText.detail[0].area]) {
|
67
|
+
delete new_areas[responseText.detail[0].area]
|
68
|
+
}
|
69
|
+
let blueprint_id = responseText.detail[0].blueprint_id;
|
70
|
+
let area_id = responseText.detail[0].area_id;
|
71
|
+
let area = responseText.detail[0].area;
|
72
|
+
editors[blueprint_id].setLayerProperties(editors[blueprint_id].map._layers[area_id], area);
|
73
|
+
editors[blueprint_id].blueprint[area_id] = area;
|
74
|
+
$callout.contents("p").html(responseText.detail[0].message);
|
75
|
+
$callout.addClass("success");
|
76
|
+
});
|
77
|
+
|
78
|
+
document.body.addEventListener("ajax:complete", () => {
|
79
|
+
$callout.show();
|
80
|
+
$modal.foundation("close");
|
81
|
+
})
|
82
|
+
|
83
|
+
$tabs.on("change.zf.tabs", (e, $tab, $content) => {
|
84
|
+
let id = $content.find(".map").data("id");
|
85
|
+
if (id) {
|
86
|
+
editors[id].reload();
|
87
|
+
}
|
88
|
+
});
|
89
|
+
|
90
|
+
$accordion.on("down.zf.accordion", () => {
|
91
|
+
let id = $accordion.find(".map").data("id");
|
92
|
+
if (id) {
|
93
|
+
editors[id].reload();
|
94
|
+
}
|
95
|
+
});
|
96
|
+
|
97
|
+
// If a new item si going to be created o the image is changed a reload is needed
|
98
|
+
let needsReload = () => {
|
99
|
+
let reload = false;
|
100
|
+
if ($form.find("#map-new input:checked").length) {
|
101
|
+
return true;
|
102
|
+
}
|
103
|
+
if ($form.find(".delete-tab input[type=checkbox]:checked").length) {
|
104
|
+
return true;
|
105
|
+
}
|
106
|
+
|
107
|
+
$form.find("input[type=file],input[tabs_id=blueprints___title]").each((_i, el) => {
|
108
|
+
if ($(el).val()) {
|
109
|
+
reload = true;
|
110
|
+
return false;
|
111
|
+
}
|
112
|
+
});
|
113
|
+
return reload;
|
114
|
+
};
|
115
|
+
|
116
|
+
$form.ajaxForm({
|
117
|
+
url: $form.find("[name=action]").val(),
|
118
|
+
beforeSerialize: () => {
|
119
|
+
Object.keys(editors).forEach((key) => {
|
120
|
+
let editor = editors[key];
|
121
|
+
$(`#blueprints_${editor.id}_blueprint`).val(JSON.stringify(editor.getBlueprint()));
|
122
|
+
});
|
123
|
+
},
|
124
|
+
beforeSend: () => {
|
125
|
+
let percentVal = "0%";
|
126
|
+
$bar.width(percentVal).html(percentVal);
|
127
|
+
$progress.show();
|
128
|
+
$callout.hide();
|
129
|
+
$callout.removeClass("alert success");
|
130
|
+
$loading.show();
|
131
|
+
},
|
132
|
+
uploadProgress: (event, position, total, percentComplete) => { // eslint-disable-line
|
133
|
+
let percentVal = `${percentComplete}%`;
|
134
|
+
$bar.width(percentVal).html(percentVal);
|
135
|
+
},
|
136
|
+
success: (responseText) => {
|
137
|
+
$callout.show();
|
138
|
+
$progress.hide();
|
139
|
+
$callout.contents("p").html(responseText);
|
140
|
+
$callout.addClass("success");
|
141
|
+
$loading.hide();
|
142
|
+
if (needsReload()) {
|
143
|
+
$loading.show();
|
144
|
+
location.reload();
|
145
|
+
}
|
146
|
+
},
|
147
|
+
error: (xhr) => {
|
148
|
+
$loading.hide();
|
149
|
+
$callout.show();
|
150
|
+
$callout.contents("p").html(xhr.responseText);
|
151
|
+
$callout.addClass("alert");
|
152
|
+
}
|
153
|
+
});
|
154
|
+
});
|
@@ -0,0 +1,125 @@
|
|
1
|
+
// Creates a map view
|
2
|
+
import "leaflet";
|
3
|
+
import "leaflet/dist/leaflet.css";
|
4
|
+
import "@geoman-io/leaflet-geoman-free";
|
5
|
+
import "@geoman-io/leaflet-geoman-free/dist/leaflet-geoman.css";
|
6
|
+
|
7
|
+
export default class NavigationMapView {
|
8
|
+
constructor(map_object, imageDecorator) {
|
9
|
+
this.features = {};
|
10
|
+
this.map_object = map_object;
|
11
|
+
this.id = map_object.dataset.id;
|
12
|
+
this.image_path = map_object.dataset.image;
|
13
|
+
this.blueprint = map_object.dataset.blueprint
|
14
|
+
? JSON.parse(map_object.dataset.blueprint)
|
15
|
+
: {};
|
16
|
+
this.image = new Image();
|
17
|
+
this.image.onload = () => {
|
18
|
+
this.createMap();
|
19
|
+
if (typeof imageDecorator === "function") {
|
20
|
+
imageDecorator(this);
|
21
|
+
} else if (this.blueprint) {
|
22
|
+
this.createAreas();
|
23
|
+
}
|
24
|
+
};
|
25
|
+
this.image.src = this.image_path;
|
26
|
+
this.clickAreaCallback = () => {};
|
27
|
+
this.setLayerPropertiesCallback = () => {};
|
28
|
+
}
|
29
|
+
|
30
|
+
createMap() {
|
31
|
+
let bounds = [[0, 0], [this.image.height, this.image.width]];
|
32
|
+
this.map = L.map(this.map_object, {
|
33
|
+
minZoom: -1,
|
34
|
+
maxZoom: 2,
|
35
|
+
crs: L.CRS.Simple,
|
36
|
+
noWrap: true,
|
37
|
+
zoomSnap: 0,
|
38
|
+
// zoomDelta: 0.1,
|
39
|
+
maxBounds: [[0, 0], [this.image.height, this.image.width]],
|
40
|
+
center: [this.image.height / 2, this.image.width / 2],
|
41
|
+
zoom: -1,
|
42
|
+
scrollWheelZoom: false,
|
43
|
+
attributionControl: false
|
44
|
+
});
|
45
|
+
|
46
|
+
L.imageOverlay(this.image.src, bounds).addTo(this.map);
|
47
|
+
this.fitBounds();
|
48
|
+
};
|
49
|
+
|
50
|
+
fitBounds() {
|
51
|
+
let image_ratio = this.image.height / this.image.width;
|
52
|
+
let map_ratio = this.map_object.offsetHeight / this.map_object.offsetWidth;
|
53
|
+
|
54
|
+
if (image_ratio > map_ratio) {
|
55
|
+
this.map.fitBounds([[0, 0], [0, this.image.width]]);
|
56
|
+
}
|
57
|
+
else {
|
58
|
+
this.map.fitBounds([[0, 0], [this.image.height, 0]]);
|
59
|
+
}
|
60
|
+
this.map.setView([this.image.height / 2, this.image.width / 2]);
|
61
|
+
};
|
62
|
+
|
63
|
+
createAreas() {
|
64
|
+
this.forEachBlueprint((id, geoarea) => {
|
65
|
+
new L.GeoJSON(geoarea, {
|
66
|
+
onEachFeature: (feature, layer) => {
|
67
|
+
layer._leaflet_id = id;
|
68
|
+
this.setLayerProperties(layer, geoarea);
|
69
|
+
this.attachEditorEvents(layer);
|
70
|
+
}
|
71
|
+
}).addTo(this.map);
|
72
|
+
});
|
73
|
+
};
|
74
|
+
|
75
|
+
setLayerProperties (layer, area) {
|
76
|
+
let props = area.properties;
|
77
|
+
if (props) {
|
78
|
+
if (props.color) {
|
79
|
+
layer.setStyle({fillColor: props.color, color: props.color});
|
80
|
+
}
|
81
|
+
this.setLayerPropertiesCallback(layer, props);
|
82
|
+
}
|
83
|
+
};
|
84
|
+
|
85
|
+
attachEditorEvents (layer) {
|
86
|
+
layer.on("mouseover", (e) => {
|
87
|
+
e.target.getElement().classList.add("selected")
|
88
|
+
});
|
89
|
+
|
90
|
+
layer.on("mouseout", (e) => {
|
91
|
+
e.target.getElement().classList.remove("selected")
|
92
|
+
});
|
93
|
+
|
94
|
+
layer.on("click", (e) => {
|
95
|
+
this.clickAreaCallback(e.target, this);
|
96
|
+
});
|
97
|
+
};
|
98
|
+
|
99
|
+
// register callback to handle area clicks
|
100
|
+
onClickArea(callback) {
|
101
|
+
this.clickAreaCallback = callback;
|
102
|
+
};
|
103
|
+
|
104
|
+
onSetLayerProperties(callback) {
|
105
|
+
this.setLayerPropertiesCallback = callback;
|
106
|
+
};
|
107
|
+
|
108
|
+
forEachBlueprint (decorator) {
|
109
|
+
for (let id in this.blueprint) {
|
110
|
+
let geoarea = this.blueprint[id];
|
111
|
+
// avoid non-polygons for the moment
|
112
|
+
if (geoarea.geometry && geoarea.geometry.type === "Polygon") {
|
113
|
+
decorator(id, geoarea);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
};
|
117
|
+
|
118
|
+
reload () {
|
119
|
+
if (this.map) {
|
120
|
+
this.map.invalidateSize(true);
|
121
|
+
this.fitBounds();
|
122
|
+
}
|
123
|
+
};
|
124
|
+
}
|
125
|
+
|