decidim-navigation_maps 1.0.1
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 +7 -0
- data/LICENSE-AGPLv3.txt +661 -0
- data/README.md +144 -0
- data/Rakefile +40 -0
- data/app/assets/config/admin/decidim_navigation_maps_manifest.css +3 -0
- data/app/assets/config/admin/decidim_navigation_maps_manifest.js +3 -0
- data/app/assets/config/decidim_navigation_maps_manifest.css +3 -0
- data/app/assets/config/decidim_navigation_maps_manifest.js +1 -0
- data/app/assets/images/decidim/navigation_maps/icon.svg +1 -0
- data/app/assets/javascripts/decidim/navigation_maps/admin/map_editor.js +88 -0
- data/app/assets/javascripts/decidim/navigation_maps/admin/navigation_maps.js +143 -0
- data/app/assets/javascripts/decidim/navigation_maps/map_view.js +123 -0
- data/app/assets/javascripts/decidim/navigation_maps/navigation_maps.js +44 -0
- data/app/assets/stylesheets/decidim/navigation_maps/_variables.scss +3 -0
- data/app/assets/stylesheets/decidim/navigation_maps/admin/navigation_maps.scss +102 -0
- data/app/assets/stylesheets/decidim/navigation_maps/navigation_maps.scss +58 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map/_styles.erb +18 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map/_tabs.erb +5 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map/_tabs_content.erb +8 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map/_template.erb +13 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map/show.erb +21 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map_cell.rb +22 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/_form.erb +36 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/_modal.erb +12 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/_tabs.erb +6 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/_tabs_content.erb +11 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form/show.erb +35 -0
- data/app/cells/decidim/navigation_maps/content_blocks/navigation_map_settings_form_cell.rb +32 -0
- data/app/commands/decidim/navigation_maps/save_area.rb +58 -0
- data/app/commands/decidim/navigation_maps/save_blueprints.rb +72 -0
- data/app/controllers/decidim/navigation_maps/admin/application_controller.rb +13 -0
- data/app/controllers/decidim/navigation_maps/admin/areas_controller.rb +94 -0
- data/app/controllers/decidim/navigation_maps/admin/blueprints_controller.rb +64 -0
- data/app/forms/decidim/navigation_maps/area_form.rb +37 -0
- data/app/forms/decidim/navigation_maps/blueprint_form.rb +39 -0
- data/app/forms/decidim/navigation_maps/blueprint_forms.rb +9 -0
- data/app/models/decidim/navigation_maps/application_record.rb +10 -0
- data/app/models/decidim/navigation_maps/blueprint.rb +27 -0
- data/app/models/decidim/navigation_maps/blueprint_area.rb +32 -0
- data/app/queries/decidim/navigation_maps/organization_blueprints.rb +20 -0
- data/app/uploaders/decidim/navigation_maps/blueprint_uploader.rb +22 -0
- data/app/views/decidim/navigation_maps/admin/areas/_form.html.erb +39 -0
- data/app/views/decidim/navigation_maps/admin/areas/new.html.erb +17 -0
- data/app/views/decidim/navigation_maps/admin/areas/show.html.erb +14 -0
- data/config/i18n-tasks.yml +10 -0
- data/config/locales/ca.yml +45 -0
- data/config/locales/cs.yml +45 -0
- data/config/locales/en.yml +46 -0
- data/config/locales/es.yml +45 -0
- data/db/migrate/20191022092624_create_decidim_navigation_maps_blueprints.rb +13 -0
- data/db/migrate/20191120185739_add_title_to_navigation_maps_blueprints.rb +10 -0
- data/db/migrate/20191125142751_create_decidim_navigation_maps_blueprint_areas.rb +18 -0
- data/db/migrate/20191126045831_add_link_type_to_decidim_navigation_maps_blueprint_areas.rb +8 -0
- data/db/migrate/20191126154019_add_area_id_to_decidim_navigation_maps_blueprint_areas.rb +16 -0
- data/db/migrate/20191127093746_add_color_to_navigation_maps_blueprint_areas.rb +7 -0
- data/lib/decidim/navigation_maps.rb +13 -0
- data/lib/decidim/navigation_maps/admin.rb +10 -0
- data/lib/decidim/navigation_maps/admin_engine.rb +34 -0
- data/lib/decidim/navigation_maps/engine.rb +34 -0
- data/lib/decidim/navigation_maps/navigation_map_cell_helpers.rb +28 -0
- data/lib/decidim/navigation_maps/test/factories.rb +29 -0
- data/lib/decidim/navigation_maps/version.rb +9 -0
- data/vendor/assets/images/draw/layers-2x.png +0 -0
- data/vendor/assets/images/draw/layers.png +0 -0
- data/vendor/assets/images/draw/marker-icon-2x.png +0 -0
- data/vendor/assets/images/draw/marker-icon.png +0 -0
- data/vendor/assets/images/draw/marker-shadow.png +0 -0
- data/vendor/assets/images/draw/spritesheet-2x.png +0 -0
- data/vendor/assets/images/draw/spritesheet.png +0 -0
- data/vendor/assets/images/draw/spritesheet.svg +156 -0
- data/vendor/assets/images/images/layers-2x.png +0 -0
- data/vendor/assets/images/images/layers.png +0 -0
- data/vendor/assets/images/images/marker-icon-2x.png +0 -0
- data/vendor/assets/images/images/marker-icon.png +0 -0
- data/vendor/assets/images/images/marker-shadow.png +0 -0
- data/vendor/assets/javascripts/jquery.form.js +1277 -0
- data/vendor/assets/javascripts/jsrender.min.js +4 -0
- data/vendor/assets/javascripts/jsrender.min.js.map +1 -0
- data/vendor/assets/javascripts/leaflet-geoman.min.js +1 -0
- data/vendor/assets/javascripts/leaflet.js +5 -0
- data/vendor/assets/stylesheets/leaflet-geoman.css +164 -0
- metadata +183 -0
data/README.md
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
# Decidim::NavigationMaps
|
2
|
+
|
3
|
+

|
4
|
+
[](https://codeclimate.com/github/Platoniq/decidim-module-navigation_maps/maintainability)
|
5
|
+
[](https://codecov.io/gh/Platoniq/decidim-module-navigation_maps)
|
6
|
+
|
7
|
+
Allows to map processes to image parts using maps.
|
8
|
+
|
9
|
+
> NOTE: This module is ready to use but in Beta status. Feel free to report any bug!
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
NavigationMaps is available as a Content Block widget (currently for the
|
14
|
+
homepage only).
|
15
|
+
|
16
|
+
👉 [Check the usage guide here!](USAGE.md)
|
17
|
+
|
18
|
+

|
19
|
+
|
20
|
+
## Installation
|
21
|
+
|
22
|
+
Add this line to your application's Gemfile:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
gem "decidim-navigation_maps", "~> 1.0.0"
|
26
|
+
```
|
27
|
+
|
28
|
+
And then execute:
|
29
|
+
|
30
|
+
```bash
|
31
|
+
bundle
|
32
|
+
bundle exec rails decidim_navigation_maps:install:migrations
|
33
|
+
bundle exec rails db:migrate
|
34
|
+
```
|
35
|
+
|
36
|
+
Depending on your Decidim version, choose the corresponding Plugin version to ensure compatibility:
|
37
|
+
|
38
|
+
| Navigation Maps version | Compatible Decidim versions |
|
39
|
+
|---|---|
|
40
|
+
| 1.0.x | 0.18.x, 0.21.x |
|
41
|
+
|
42
|
+
## Contributing
|
43
|
+
|
44
|
+
See [Decidim](https://github.com/decidim/decidim).
|
45
|
+
|
46
|
+
### Developing
|
47
|
+
|
48
|
+
To start contributing to this project, first:
|
49
|
+
|
50
|
+
- Install the basic dependencies (such as Ruby and PostgreSQL)
|
51
|
+
- Clone this repository
|
52
|
+
|
53
|
+
Decidim's main repository also provides a Docker configuration file if you
|
54
|
+
prefer to use Docker instead of installing the dependencies locally on your
|
55
|
+
machine.
|
56
|
+
|
57
|
+
You can create the development app by running the following commands after
|
58
|
+
cloning this project:
|
59
|
+
|
60
|
+
```bash
|
61
|
+
bundle
|
62
|
+
DATABASE_USERNAME=<username> DATABASE_PASSWORD=<password> bundle exec rake development_app
|
63
|
+
```
|
64
|
+
|
65
|
+
Note that the database user has to have rights to create and drop a database in
|
66
|
+
order to create the dummy test app database.
|
67
|
+
|
68
|
+
Then to test how the module works in Decidim, start the development server:
|
69
|
+
|
70
|
+
```bash
|
71
|
+
cd development_app
|
72
|
+
DATABASE_USERNAME=<username> DATABASE_PASSWORD=<password> bundle exec rails s
|
73
|
+
```
|
74
|
+
|
75
|
+
In case you are using [rbenv](https://github.com/rbenv/rbenv) and have the
|
76
|
+
[rbenv-vars](https://github.com/rbenv/rbenv-vars) plugin installed for it, you
|
77
|
+
can add the environment variables to the root directory of the project in a file
|
78
|
+
named `.rbenv-vars`. If these are defined for the environment, you can omit
|
79
|
+
defining these in the commands shown above.
|
80
|
+
|
81
|
+
#### Code Styling
|
82
|
+
|
83
|
+
Please follow the code styling defined by the different linters that ensure we
|
84
|
+
are all talking with the same language collaborating on the same project. This
|
85
|
+
project is set to follow the same rules that Decidim itself follows.
|
86
|
+
|
87
|
+
[Rubocop](https://rubocop.readthedocs.io/) linter is used for the Ruby language.
|
88
|
+
|
89
|
+
You can run the code styling checks by running the following commands from the
|
90
|
+
console:
|
91
|
+
|
92
|
+
```
|
93
|
+
bundle exec rubocop
|
94
|
+
```
|
95
|
+
|
96
|
+
To ease up following the style guide, you should install the plugin to your
|
97
|
+
favorite editor, such as:
|
98
|
+
|
99
|
+
- Atom - [linter-rubocop](https://atom.io/packages/linter-rubocop)
|
100
|
+
- Sublime Text - [Sublime RuboCop](https://github.com/pderichs/sublime_rubocop)
|
101
|
+
- Visual Studio Code - [Rubocop for Visual Studio Code](https://github.com/misogi/vscode-ruby-rubocop)
|
102
|
+
|
103
|
+
### Testing
|
104
|
+
|
105
|
+
To run the tests run the following in the gem development path:
|
106
|
+
|
107
|
+
```bash
|
108
|
+
bundle
|
109
|
+
DATABASE_USERNAME=<username> DATABASE_PASSWORD=<password> bundle exec rake test_app
|
110
|
+
DATABASE_USERNAME=<username> DATABASE_PASSWORD=<password> bundle exec rspec
|
111
|
+
```
|
112
|
+
|
113
|
+
Note that the database user has to have rights to create and drop a database in
|
114
|
+
order to create the dummy test app database.
|
115
|
+
|
116
|
+
In case you are using [rbenv](https://github.com/rbenv/rbenv) and have the
|
117
|
+
[rbenv-vars](https://github.com/rbenv/rbenv-vars) plugin installed for it, you
|
118
|
+
can add these environment variables to the root directory of the project in a
|
119
|
+
file named `.rbenv-vars`. In this case, you can omit defining these in the
|
120
|
+
commands shown above.
|
121
|
+
|
122
|
+
### Test code coverage
|
123
|
+
|
124
|
+
If you want to generate the code coverage report for the tests, you can use
|
125
|
+
the `SIMPLECOV=1` environment variable in the rspec command as follows:
|
126
|
+
|
127
|
+
```bash
|
128
|
+
SIMPLECOV=1 bundle exec rspec
|
129
|
+
```
|
130
|
+
|
131
|
+
This will generate a folder named `coverage` in the project root which contains
|
132
|
+
the code coverage report.
|
133
|
+
|
134
|
+
## License
|
135
|
+
|
136
|
+
This engine is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
|
137
|
+
|
138
|
+
## Credits
|
139
|
+
|
140
|
+
This plugin has been developed by 
|
141
|
+
|
142
|
+
> Amb el suport de l'Ajuntament de Barcelona - Direcció de Serveis d'Innovació Democràtica
|
143
|
+
>
|
144
|
+
> 
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "decidim/dev/common_rake"
|
4
|
+
|
5
|
+
def install_module(path)
|
6
|
+
Dir.chdir(path) do
|
7
|
+
system("bundle exec rake decidim_navigation_maps:install:migrations")
|
8
|
+
system("bundle exec rake db:migrate")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def seed_db(path)
|
13
|
+
Dir.chdir(path) do
|
14
|
+
system("bundle exec rake db:seed")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Generates a dummy app for testing"
|
19
|
+
task test_app: "decidim:generate_external_test_app" do
|
20
|
+
ENV["RAILS_ENV"] = "test"
|
21
|
+
install_module("spec/decidim_dummy_app")
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "Generates a development app"
|
25
|
+
task :development_app do
|
26
|
+
Bundler.with_original_env do
|
27
|
+
generate_decidim_app(
|
28
|
+
"development_app",
|
29
|
+
"--app_name",
|
30
|
+
"#{base_app_name}_development_app",
|
31
|
+
"--path",
|
32
|
+
"..",
|
33
|
+
"--recreate_db",
|
34
|
+
"--demo"
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
install_module("development_app")
|
39
|
+
seed_db("development_app")
|
40
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link decidim/navigation_maps/navigation_maps.js
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg height="35px" width="35px" fill="#000000" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 1 511 511" style="enable-background:new 0 1 511 511;" xml:space="preserve"><g><path d="M205.6,146.9c-22.2,0-40.2,18-40.2,40.2c0,22.2,18,40.2,40.2,40.2c22.2,0,40.2-18,40.2-40.2 C245.9,165,227.8,146.9,205.6,146.9z M205.6,206.6c-10.7,0-19.3-8.7-19.3-19.3c0-10.7,8.7-19.3,19.3-19.3 c10.6,0,19.3,8.7,19.3,19.3C225,197.9,216.3,206.6,205.6,206.6z"/><path d="M406.6,178V70.3c0-5.8-4.2-10.1-10-10.1H10.6C4.8,60.3,0,64.6,0,70.3v304.9c0,5.8,4.8,10.9,10.6,10.9h242 c24.5,39.8,68.7,66.7,119.1,66.7c77,0,139.4-62.8,139.4-139.7C511,248.4,467.4,193.7,406.6,178z M21,365.2v-284h364.7v92.9 c-4.2-0.5-9.1-0.7-14-0.7c-0.3,0-0.6,0-0.6,0v-66.4c0-5.8-5-10-10.9-10H47.2c-5.8,0-10.5,4.2-10.5,10v231.8 c0,5.8,4.7,10.8,10.5,10.8h189.7c1.5,5.2,3.1,10.5,5.2,15.7H21z M232.9,328.6H57.6v-40.4l61.5-54.3c2.8-2.5,7-2.6,10-0.2l63.3,50.6 c10.7,8.6,26,8.4,36.5-0.5l7.6-6.5c-3,11.4-4.6,23.6-4.6,35.8C232,318.3,232.3,323.3,232.9,328.6z M215.7,267.8 c-2.8,2.4-7,2.4-10,0.1l-63.4-50.6c-10.9-8.7-26.5-8.4-37,0.9l-47.7,42V117.9H350v57.2c-37.7,6-70.1,26.8-91.4,56.4L215.7,267.8z M371.6,431.7C306.2,431.7,253,378.4,253,313s53.2-118.6,118.6-118.6c65.4,0,118.6,53.2,118.6,118.6 C490.4,378.4,437.1,431.7,371.6,431.7z"/><path d="M435.4,234c-34.8-34.6-91-34.6-125.6,0c-13.7,13.7-22.4,31.2-25,50.4c-2.5,18.5,0.9,37.8,9.9,54.4c0,0,0,0.1,0.1,0.1 c4.4,8,9.4,14.7,15.2,20.4l55.1,55.1c2,2,4.6,3,7.4,3s5.5-1.2,7.4-3l55.1-55.1c16.9-16.9,26.2-39.2,26.2-62.8 C461.4,273,452.2,250.7,435.4,234z M420.1,344.6l-47.7,47.7l-47.7-47.7c-4.4-4.4-8.2-9.5-11.6-15.7c-14.2-26.6-9.6-58.8,11.6-80.1 c26.4-26.4,69.4-26.4,95.8,0c12.8,12.8,19.8,29.8,19.7,47.7C440.2,314.6,433,331.7,420.1,344.6z"/><path d="M372.3,241.7c-29,0-52.7,23.7-52.7,52.7c0,29,23.7,52.7,52.7,52.7s52.7-23.7,52.7-52.7 C425.1,265.4,401.5,241.7,372.3,241.7z M372.3,326c-17.5,0-31.8-14.2-31.8-31.8c0-17.5,14.3-31.8,31.8-31.8 c17.5,0,31.8,14.3,31.8,31.8C404.1,311.8,389.9,326,372.3,326z"/></g></svg>
|
@@ -0,0 +1,88 @@
|
|
1
|
+
// Creates a map
|
2
|
+
//= require decidim/navigation_maps/map_view
|
3
|
+
|
4
|
+
function NavigationMapEditor(map_object, table_object) {
|
5
|
+
var self = this;
|
6
|
+
// Call constructor of superclass to initialize superclass-derived members.
|
7
|
+
NavigationMapView.call(self, map_object, function() {
|
8
|
+
self.createControls();
|
9
|
+
if(self.blueprint) {
|
10
|
+
self.createAreas();
|
11
|
+
}
|
12
|
+
});
|
13
|
+
self.table_object = table_object;
|
14
|
+
this.createAreaCallback = function () {};
|
15
|
+
this.editAreaCallback = function () {};
|
16
|
+
this.removeAreaCallback = function () {};
|
17
|
+
}
|
18
|
+
|
19
|
+
// NavigationMapEditor derives from NavigationMapView
|
20
|
+
NavigationMapEditor.prototype = Object.create(NavigationMapView.prototype);
|
21
|
+
NavigationMapEditor.prototype.constructor = NavigationMapEditor;
|
22
|
+
|
23
|
+
NavigationMapEditor.prototype.createControls = function() {
|
24
|
+
var self = this;
|
25
|
+
self.map.pm.addControls({
|
26
|
+
position: 'topleft',
|
27
|
+
drawCircle: false,
|
28
|
+
drawMarker: false,
|
29
|
+
drawCircleMarker: false,
|
30
|
+
drawPolyline: false,
|
31
|
+
cutPolygon: false
|
32
|
+
});
|
33
|
+
|
34
|
+
self.map.on('pm:create', function(e) {
|
35
|
+
var geojson = e.layer.toGeoJSON();
|
36
|
+
self.blueprint[e.layer._leaflet_id] = geojson;
|
37
|
+
self.attachEditorEvents(e.layer);
|
38
|
+
self.createAreaCallback(e.layer._leaflet_id, e.layer, self);
|
39
|
+
});
|
40
|
+
|
41
|
+
self.map.on('pm:remove', function(e) {
|
42
|
+
delete self.blueprint[e.layer._leaflet_id];
|
43
|
+
self.removeAreaCallback(e.layer._leaflet_id, e.layer, self);
|
44
|
+
});
|
45
|
+
};
|
46
|
+
|
47
|
+
NavigationMapEditor.prototype.editing = function() {
|
48
|
+
var pm = this.map.pm;
|
49
|
+
return pm.globalRemovalEnabled() || pm.globalDragModeEnabled() || pm.globalEditEnabled();
|
50
|
+
};
|
51
|
+
|
52
|
+
// register callback to handle area edits,removals and creations
|
53
|
+
NavigationMapView.prototype.onCreateArea = function(callback) {
|
54
|
+
this.createAreaCallback = callback;
|
55
|
+
};
|
56
|
+
NavigationMapView.prototype.onEditArea = function(callback) {
|
57
|
+
this.editAreaCallback = callback;
|
58
|
+
};
|
59
|
+
NavigationMapView.prototype.onRemoveArea = function(callback) {
|
60
|
+
this.removeCreateCallback = callback;
|
61
|
+
};
|
62
|
+
|
63
|
+
NavigationMapEditor.prototype.attachEditorEvents = function (layer) {
|
64
|
+
var self = this;
|
65
|
+
|
66
|
+
layer.on('mouseover', function(e) {
|
67
|
+
e.target.getElement().classList.add('selected')
|
68
|
+
});
|
69
|
+
|
70
|
+
layer.on('mouseout', function(e) {
|
71
|
+
e.target.getElement().classList.remove('selected')
|
72
|
+
});
|
73
|
+
|
74
|
+
layer.on('pm:edit', function(e) {
|
75
|
+
self.blueprint[e.target._leaflet_id] = e.target.toGeoJSON();
|
76
|
+
self.editAreaCallback(e.target._leaflet_id, e.target, self);
|
77
|
+
});
|
78
|
+
|
79
|
+
layer.on('click', function(e) {
|
80
|
+
if(!self.editing()) {
|
81
|
+
self.clickAreaCallback(e.target._leaflet_id, e.target, self);
|
82
|
+
}
|
83
|
+
});
|
84
|
+
};
|
85
|
+
|
86
|
+
NavigationMapEditor.prototype.getBlueprint = function () {
|
87
|
+
return this.blueprint;
|
88
|
+
};
|
@@ -0,0 +1,143 @@
|
|
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
|
+
//= require jquery.form
|
4
|
+
//= require decidim/navigation_maps/admin/map_editor
|
5
|
+
//= require_self
|
6
|
+
|
7
|
+
$(function() {
|
8
|
+
|
9
|
+
var $maps = $('.navigation_maps.admin .map');
|
10
|
+
var $progress = $('.navigation_maps.admin .progress');
|
11
|
+
var $bar = $('.navigation_maps.admin .progress-meter');
|
12
|
+
var $loading = $('.navigation_maps.admin .loading');
|
13
|
+
var $callout = $('.navigation_maps.admin .callout');
|
14
|
+
var $modal = $('#mapEditModal');
|
15
|
+
var $form = $('form');
|
16
|
+
var $tabs = $('#navigation_maps-tabs');
|
17
|
+
var $accordion = $('.navigation_maps.admin .accordion');
|
18
|
+
var editors = {};
|
19
|
+
var new_areas = {};
|
20
|
+
|
21
|
+
$maps.each(function() {
|
22
|
+
var id = $(this).data('id');
|
23
|
+
var table = document.getElementById("navigation_maps-table-" + id);
|
24
|
+
editors[id] = new NavigationMapEditor(this, table);
|
25
|
+
editors[id].onCreateArea(function(area_id) {
|
26
|
+
new_areas[area_id] = true;
|
27
|
+
});
|
28
|
+
|
29
|
+
editors[id].onClickArea(function(area_id, area) {
|
30
|
+
$modal.find('.modal-content').html('');
|
31
|
+
$modal.addClass('loading').foundation('open');
|
32
|
+
$callout.hide();
|
33
|
+
$callout.removeClass('alert success');
|
34
|
+
// "new" form insted of editing
|
35
|
+
var rel = new_areas[area_id] ? 'new' : area_id;
|
36
|
+
$modal.find('.modal-content').load(`/admin/navigation_maps/blueprints/${id}/areas/${rel}`, function() {
|
37
|
+
var $input1 = $modal.find('input[name="blueprint_area[area_id]"]');
|
38
|
+
var $input2 = $modal.find('input[name="blueprint_area[area_type]"]');
|
39
|
+
var $input3 = $modal.find('input[name="blueprint_area[area]"]');
|
40
|
+
var a = area.toGeoJSON();
|
41
|
+
$modal.removeClass('loading');
|
42
|
+
if($input1.length) $input1.val(area_id);
|
43
|
+
if($input2.length) $input2.val(a.type);
|
44
|
+
if($input3.length) $input3.val(JSON.stringify(a));
|
45
|
+
$modal.find('ul[data-tabs=true]').each(function() {
|
46
|
+
new Foundation.Tabs($(this));
|
47
|
+
});
|
48
|
+
});
|
49
|
+
});
|
50
|
+
});
|
51
|
+
|
52
|
+
// Rails AJAX events
|
53
|
+
document.body.addEventListener('ajax:error', function(responseText) {
|
54
|
+
$callout.contents('p').html(responseText.detail[0].message + ": <strong>" + responseText.detail[0].error + "</strong>");
|
55
|
+
$callout.addClass('alert');
|
56
|
+
});
|
57
|
+
|
58
|
+
document.body.addEventListener('ajax:success', function(responseText) {
|
59
|
+
if(new_areas[responseText.detail[0].area]) {
|
60
|
+
delete new_areas[responseText.detail[0].area]
|
61
|
+
}
|
62
|
+
var blueprint_id = responseText.detail[0].blueprint_id;
|
63
|
+
var area_id = responseText.detail[0].area_id;
|
64
|
+
var area = responseText.detail[0].area;
|
65
|
+
editors[blueprint_id].setLayerProperties(editors[blueprint_id].map._layers[area_id], area);
|
66
|
+
editors[blueprint_id].blueprint[area_id] = area;
|
67
|
+
$callout.contents('p').html(responseText.detail[0].message);
|
68
|
+
$callout.addClass('success');
|
69
|
+
});
|
70
|
+
|
71
|
+
document.body.addEventListener('ajax:complete', function() {
|
72
|
+
$callout.show();
|
73
|
+
$modal.foundation('close');
|
74
|
+
})
|
75
|
+
|
76
|
+
$tabs.on('change.zf.tabs', function(e, $tab, $content) {
|
77
|
+
var id = $content.find('.map').data('id');
|
78
|
+
if(id) {
|
79
|
+
editors[id].reload();
|
80
|
+
}
|
81
|
+
});
|
82
|
+
|
83
|
+
$accordion.on('down.zf.accordion', function(e, $accordion) {
|
84
|
+
var id = $accordion.find('.map').data('id');
|
85
|
+
if(id) {
|
86
|
+
editors[id].reload();
|
87
|
+
}
|
88
|
+
});
|
89
|
+
|
90
|
+
// If a new item si going to be created o the image is changed a reload is needed
|
91
|
+
var needsReload = function() {
|
92
|
+
var reload = false;
|
93
|
+
if($form.find('#map-new input:checked').length) return true;
|
94
|
+
if($form.find('.delete-tab input[type=checkbox]:checked').length) return true;
|
95
|
+
|
96
|
+
$form.find('input[type=file],input[tabs_id=blueprints___title]').each(function() {
|
97
|
+
if($(this).val()) {
|
98
|
+
reload = true;
|
99
|
+
return false;
|
100
|
+
}
|
101
|
+
});
|
102
|
+
return reload;
|
103
|
+
};
|
104
|
+
|
105
|
+
$form.ajaxForm({
|
106
|
+
url: $form.find('[name=action]').val(),
|
107
|
+
beforeSerialize: function() {
|
108
|
+
Object.keys(editors).forEach(function(key) {
|
109
|
+
var editor = editors[key];
|
110
|
+
$(`#blueprints_${editor.id}_blueprint`).val(JSON.stringify(editor.getBlueprint()));
|
111
|
+
});
|
112
|
+
},
|
113
|
+
beforeSend: function() {
|
114
|
+
var percentVal = '0%';
|
115
|
+
$bar.width(percentVal).html(percentVal);
|
116
|
+
$progress.show();
|
117
|
+
$callout.hide();
|
118
|
+
$callout.removeClass('alert success');
|
119
|
+
$loading.show();
|
120
|
+
},
|
121
|
+
uploadProgress: function(event, position, total, percentComplete) {
|
122
|
+
var percentVal = percentComplete + '%';
|
123
|
+
$bar.width(percentVal).html(percentVal);
|
124
|
+
},
|
125
|
+
success: function(responseText) {
|
126
|
+
$callout.show();
|
127
|
+
$progress.hide();
|
128
|
+
$callout.contents('p').html(responseText);
|
129
|
+
$callout.addClass('success');
|
130
|
+
$loading.hide();
|
131
|
+
if(needsReload()) {
|
132
|
+
$loading.show();
|
133
|
+
location.reload();
|
134
|
+
}
|
135
|
+
},
|
136
|
+
error: function(xhr) {
|
137
|
+
$loading.hide();
|
138
|
+
$callout.show();
|
139
|
+
$callout.contents('p').html(xhr.responseText);
|
140
|
+
$callout.addClass('alert');
|
141
|
+
}
|
142
|
+
});
|
143
|
+
});
|
@@ -0,0 +1,123 @@
|
|
1
|
+
// Creates a map view
|
2
|
+
//= require leaflet
|
3
|
+
//= require leaflet-geoman.min
|
4
|
+
|
5
|
+
function NavigationMapView(map_object, callback) {
|
6
|
+
var self = this;
|
7
|
+
self.features = {};
|
8
|
+
self.map_object = map_object;
|
9
|
+
self.id = map_object.dataset.id;
|
10
|
+
self.image_path = map_object.dataset.image;
|
11
|
+
self.blueprint = map_object.dataset.blueprint ? JSON.parse(map_object.dataset.blueprint) : {};
|
12
|
+
self.image = new Image();
|
13
|
+
self.image.onload = function() {
|
14
|
+
self.createMap();
|
15
|
+
if(typeof callback === "function") {
|
16
|
+
callback(self);
|
17
|
+
} else {
|
18
|
+
if(self.blueprint) {
|
19
|
+
self.createAreas();
|
20
|
+
}
|
21
|
+
}
|
22
|
+
};
|
23
|
+
self.image.src = self.image_path;
|
24
|
+
this.clickAreaCallback = function () {};
|
25
|
+
this.setLayerPropertiesCallback = function () {};
|
26
|
+
}
|
27
|
+
|
28
|
+
NavigationMapView.prototype.createMap = function() {
|
29
|
+
var bounds = [[0,0], [this.image.height,this.image.width]];
|
30
|
+
|
31
|
+
this.map = L.map(this.map_object, {
|
32
|
+
minZoom: -1,
|
33
|
+
maxZoom: 2,
|
34
|
+
crs: L.CRS.Simple,
|
35
|
+
noWrap: true,
|
36
|
+
zoomSnap: 0,
|
37
|
+
// zoomDelta: 0.1,
|
38
|
+
maxBounds: [[0,0], [this.image.height,this.image.width]],
|
39
|
+
center: [this.image.height/2, this.image.width/2],
|
40
|
+
zoom: -1,
|
41
|
+
scrollWheelZoom: false
|
42
|
+
});
|
43
|
+
|
44
|
+
L.imageOverlay(this.image.src, bounds).addTo(this.map);
|
45
|
+
this.fitBounds();
|
46
|
+
};
|
47
|
+
|
48
|
+
NavigationMapView.prototype.fitBounds = function() {
|
49
|
+
var image_ratio = this.image.height / this.image.width;
|
50
|
+
var map_ratio = this.map_object.offsetHeight / this.map_object.offsetWidth;
|
51
|
+
|
52
|
+
if(image_ratio > map_ratio) {
|
53
|
+
this.map.fitBounds([[0,0], [0,this.image.width]]);
|
54
|
+
}
|
55
|
+
else {
|
56
|
+
this.map.fitBounds([[0,0], [this.image.height,0]]);
|
57
|
+
}
|
58
|
+
this.map.setView([this.image.height/2, this.image.width/2]);
|
59
|
+
};
|
60
|
+
|
61
|
+
NavigationMapView.prototype.createAreas = function() {
|
62
|
+
var self = this;
|
63
|
+
self.forEachBlueprint(function(id, geoarea) {
|
64
|
+
new L.GeoJSON(geoarea, {
|
65
|
+
onEachFeature: function(feature, layer) {
|
66
|
+
layer._leaflet_id = id;
|
67
|
+
self.setLayerProperties(layer, geoarea);
|
68
|
+
self.attachEditorEvents(layer);
|
69
|
+
}
|
70
|
+
}).addTo(self.map);
|
71
|
+
});
|
72
|
+
};
|
73
|
+
|
74
|
+
NavigationMapView.prototype.setLayerProperties = function (layer, area) {
|
75
|
+
var props = area.properties;
|
76
|
+
if(props) {
|
77
|
+
if(props.color) {
|
78
|
+
layer.setStyle({fillColor: props.color, color: props.color});
|
79
|
+
}
|
80
|
+
this.setLayerPropertiesCallback(layer, props);
|
81
|
+
}
|
82
|
+
};
|
83
|
+
|
84
|
+
NavigationMapView.prototype.attachEditorEvents = function (layer) {
|
85
|
+
var self = this;
|
86
|
+
|
87
|
+
layer.on('mouseover', function(e) {
|
88
|
+
e.target.getElement().classList.add('selected')
|
89
|
+
});
|
90
|
+
|
91
|
+
layer.on('mouseout', function(e) {
|
92
|
+
e.target.getElement().classList.remove('selected')
|
93
|
+
});
|
94
|
+
|
95
|
+
layer.on('click', function(e) {
|
96
|
+
self.clickAreaCallback(e.target, self);
|
97
|
+
});
|
98
|
+
};
|
99
|
+
|
100
|
+
// register callback to handle area clicks
|
101
|
+
NavigationMapView.prototype.onClickArea = function(callback) {
|
102
|
+
this.clickAreaCallback = callback;
|
103
|
+
};
|
104
|
+
|
105
|
+
NavigationMapView.prototype.onSetLayerProperties = function(callback) {
|
106
|
+
this.setLayerPropertiesCallback = callback;
|
107
|
+
};
|
108
|
+
|
109
|
+
NavigationMapView.prototype.forEachBlueprint = function (callback) {
|
110
|
+
for (var id in this.blueprint) {
|
111
|
+
var geoarea = this.blueprint[id];
|
112
|
+
// avoid non-polygons for the moment
|
113
|
+
if(!geoarea.geometry || geoarea.geometry.type !== 'Polygon') continue;
|
114
|
+
callback(id, geoarea);
|
115
|
+
}
|
116
|
+
};
|
117
|
+
|
118
|
+
NavigationMapView.prototype.reload = function () {
|
119
|
+
if(this.map) {
|
120
|
+
this.map.invalidateSize(true);
|
121
|
+
this.fitBounds();
|
122
|
+
}
|
123
|
+
};
|