decidim-decidim_geo 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-AGPLv3.txt +661 -0
  3. data/README.md +172 -0
  4. data/Rakefile +119 -0
  5. data/app/cells/decidim/geo/content_blocks/geo_maps/show.erb +15 -0
  6. data/app/cells/decidim/geo/content_blocks/geo_maps_cell.rb +114 -0
  7. data/app/cells/decidim/geo/content_blocks/geo_maps_settings_form_cell.rb +14 -0
  8. data/app/cells/decidim/geo/geo_collection_map/show.erb +4 -0
  9. data/app/cells/decidim/geo/geo_collection_map_cell.rb +102 -0
  10. data/app/commands/decidim/admin/create_scope.rb +56 -0
  11. data/app/commands/decidim/admin/create_scope_type.rb +47 -0
  12. data/app/commands/decidim/admin/update_scope.rb +60 -0
  13. data/app/commands/decidim/admin/update_scope_type.rb +62 -0
  14. data/app/commands/decidim/geo/admin/create_shapefile.rb +51 -0
  15. data/app/commands/decidim/geo/admin/update_geo_config.rb +54 -0
  16. data/app/commands/decidim/geo/command.rb +14 -0
  17. data/app/controllers/decidim/admin/scopes_controller.rb +115 -0
  18. data/app/controllers/decidim/geo/admin/application_controller.rb +21 -0
  19. data/app/controllers/decidim/geo/admin/geo_configs_controller.rb +44 -0
  20. data/app/controllers/decidim/geo/admin/shapefiles_controller.rb +41 -0
  21. data/app/controllers/decidim/geo/application_controller.rb +13 -0
  22. data/app/controllers/decidim/geo/shapefile_controller.rb +11 -0
  23. data/app/forms/decidim/admin/scope_form.rb +43 -0
  24. data/app/forms/decidim/admin/scope_type_form.rb +27 -0
  25. data/app/forms/decidim/geo/admin/geo_config_form.rb +20 -0
  26. data/app/forms/decidim/geo/admin/shapefile_form.rb +23 -0
  27. data/app/helpers/decidim/admin/scopes_helper.rb +72 -0
  28. data/app/jobs/decidim/geo/shp2pgsql_job.rb +14 -0
  29. data/app/models/decidim/debates/debate.rb +226 -0
  30. data/app/models/decidim/geo/application_record.rb +10 -0
  31. data/app/models/decidim/geo/geo_config.rb +28 -0
  32. data/app/models/decidim/geo/shapedata.rb +23 -0
  33. data/app/models/decidim/geo/shapefile.rb +27 -0
  34. data/app/models/decidim/geo/space_location.rb +16 -0
  35. data/app/models/decidim/scope.rb +111 -0
  36. data/app/models/decidim/scope_type.rb +26 -0
  37. data/app/overrides/decidim/assemblies/admin/assemblies/_form/insert_location_form.html.erb.deface +13 -0
  38. data/app/overrides/decidim/assemblies/assemblies/show/insert_location.html.erb.deface +7 -0
  39. data/app/overrides/decidim/participatory_processes/admin/participatory_processes/_form/insert_location_form.html.erb.deface +13 -0
  40. data/app/overrides/decidim/participatory_processes/participatory_process_groups/show/insert_map.html.erb.deface +6 -0
  41. data/app/overrides/layouts/decidim/_assembly_header/insert_map.html.erb.deface +25 -0
  42. data/app/overrides/layouts/decidim/_process_header/insert_map.html.erb.deface +22 -0
  43. data/app/overrides/layouts/decidim/_wrapper/insert_map.html.erb.deface +5 -0
  44. data/app/overrides/remove_default_meetings_map.rb +4 -0
  45. data/app/overrides/remove_default_proposals_map.rb +4 -0
  46. data/app/packs/entrypoints/decidim_geo.js +3 -0
  47. data/app/packs/images/decidim/geo/not-geolocated.svg +3 -0
  48. data/app/packs/src/decidim/geo/actions/index.js +25 -0
  49. data/app/packs/src/decidim/geo/api/index.js +53 -0
  50. data/app/packs/src/decidim/geo/api/queries.js +77 -0
  51. data/app/packs/src/decidim/geo/bootstrap.js +6 -0
  52. data/app/packs/src/decidim/geo/index.js +101 -0
  53. data/app/packs/src/decidim/geo/models/configStore.js +44 -0
  54. data/app/packs/src/decidim/geo/models/dropdownFilterStore.js +65 -0
  55. data/app/packs/src/decidim/geo/models/filterStore.js +121 -0
  56. data/app/packs/src/decidim/geo/models/geoDatasourceNode/GeoDatasourceNode.js +124 -0
  57. data/app/packs/src/decidim/geo/models/geoDatasourceNode/index.js +1 -0
  58. data/app/packs/src/decidim/geo/models/geoScope/GeoScope.js +128 -0
  59. data/app/packs/src/decidim/geo/models/geoScope/index.js +1 -0
  60. data/app/packs/src/decidim/geo/models/geoStore.js +118 -0
  61. data/app/packs/src/decidim/geo/models/pointStore.js +134 -0
  62. data/app/packs/src/decidim/geo/models/scopeDropdownStore.js +20 -0
  63. data/app/packs/src/decidim/geo/ui/DrawerDetail/fallback.js +42 -0
  64. data/app/packs/src/decidim/geo/ui/DrawerDetail/index.js +2 -0
  65. data/app/packs/src/decidim/geo/ui/DrawerDetail/meetings.js +75 -0
  66. data/app/packs/src/decidim/geo/ui/DrawerMenuItem/fallback.js +45 -0
  67. data/app/packs/src/decidim/geo/ui/DrawerMenuItem/index.js +2 -0
  68. data/app/packs/src/decidim/geo/ui/DrawerMenuItem/meetings.js +62 -0
  69. data/app/packs/src/decidim/geo/ui/createClasses.js +7 -0
  70. data/app/packs/src/decidim/geo/ui/createCustomMarker.js +14 -0
  71. data/app/packs/src/decidim/geo/ui/createDomElement.js +2 -0
  72. data/app/packs/src/decidim/geo/ui/createDrawer.js +170 -0
  73. data/app/packs/src/decidim/geo/ui/createDrawerActions.js +197 -0
  74. data/app/packs/src/decidim/geo/ui/createFilterDropdown.js +320 -0
  75. data/app/packs/src/decidim/geo/ui/createGeoScopeLayer.js +20 -0
  76. data/app/packs/src/decidim/geo/ui/createGeoScopeMenuItem.js +8 -0
  77. data/app/packs/src/decidim/geo/ui/createNodeMarker.js +9 -0
  78. data/app/packs/src/decidim/geo/ui/createNodeMenuItem.js +13 -0
  79. data/app/packs/src/decidim/geo/ui/index.js +8 -0
  80. data/app/packs/src/decidim/geo/ui/initMap.js +22 -0
  81. data/app/packs/src/decidim/geo/utils/index.js +30 -0
  82. data/app/packs/src/decidim/geo/utils/saveConfig.js +15 -0
  83. data/app/packs/stylesheets/decidim/geo/_geo.scss +2 -0
  84. data/app/packs/stylesheets/decidim/geo/geo/_decidim_geo_decidimGeo.scss +476 -0
  85. data/app/packs/stylesheets/decidim/geo/geo/_decidim_geo_override.scss +65 -0
  86. data/app/permissions/decidim/geo/admin/permissions.rb +24 -0
  87. data/app/permissions/decidim/geo/permissions.rb +15 -0
  88. data/app/uploaders/decidim/geo/shapefile_uploader.rb +14 -0
  89. data/app/validators/geocoding_validator.rb +30 -0
  90. data/app/views/decidim/admin/scope_types/_form.html.erb +10 -0
  91. data/app/views/decidim/admin/scope_types/index.html.erb +46 -0
  92. data/app/views/decidim/admin/scopes/_form.html.erb +20 -0
  93. data/app/views/decidim/admin/scopes/index.html.erb +55 -0
  94. data/app/views/decidim/geo/admin/geo_configs/_form.html.erb +47 -0
  95. data/app/views/decidim/geo/admin/geo_configs/index.html.erb +8 -0
  96. data/app/views/decidim/geo/admin/shapefiles/_form.html.erb +29 -0
  97. data/app/views/decidim/geo/admin/shapefiles/index.html.erb +38 -0
  98. data/app/views/decidim/geo/admin/shapefiles/new.html.erb +8 -0
  99. data/app/views/layouts/decidim/decidim_geo/admin/application.html.erb +19 -0
  100. data/config/assets.rb +9 -0
  101. data/config/i18n-tasks.yml +10 -0
  102. data/config/locales/de.yml +102 -0
  103. data/config/locales/en.yml +108 -0
  104. data/config/locales/fr.yml +102 -0
  105. data/db/migrate/20221019184712_add_postgis_extension_to_database.rb +5 -0
  106. data/db/migrate/20221025195520_create_decidim_geo.rb +22 -0
  107. data/db/migrate/20231013082325_create_decidim_geo_config.rb +11 -0
  108. data/db/migrate/20231206115531_add_spaces_config_to_decidim_geo_configs.rb +6 -0
  109. data/db/migrate/20240309004347_add_organization_to_shapefiles.rb +6 -0
  110. data/db/migrate/20240326052727_create_space_locations.rb +18 -0
  111. data/lib/decidim/api/geo_config_type.rb +15 -0
  112. data/lib/decidim/api/geo_coordinates_type.rb +22 -0
  113. data/lib/decidim/api/geo_datasource_type.rb +147 -0
  114. data/lib/decidim/api/geo_dates_type.rb +15 -0
  115. data/lib/decidim/api/geo_query_extension.rb +25 -0
  116. data/lib/decidim/api/geo_scope_api_type.rb +26 -0
  117. data/lib/decidim/api/geo_shapedata_type.rb +18 -0
  118. data/lib/decidim/api/geo_shapefile_type.rb +22 -0
  119. data/lib/decidim/api/input_filters/assembly_input_filter.rb +13 -0
  120. data/lib/decidim/api/input_filters/geo_datasource_input_filter.rb +18 -0
  121. data/lib/decidim/api/input_filters/geoencoded_input_filter.rb +13 -0
  122. data/lib/decidim/api/input_filters/has_scopeable_input_filter.rb +17 -0
  123. data/lib/decidim/api/input_filters/process_input_filter.rb +13 -0
  124. data/lib/decidim/api/input_filters/resource_type_input_filter.rb +13 -0
  125. data/lib/decidim/api/input_filters/scope_input_filter.rb +13 -0
  126. data/lib/decidim/api/input_filters/time_input_filter.rb +13 -0
  127. data/lib/decidim/api/meetings_input_filter.rb +14 -0
  128. data/lib/decidim/api/query_extension.rb +320 -0
  129. data/lib/decidim/api/shapefile_query_extention.rb +18 -0
  130. data/lib/decidim/api/shapefile_type.rb +18 -0
  131. data/lib/decidim/decidim_geo/admin.rb +10 -0
  132. data/lib/decidim/decidim_geo/admin_engine.rb +69 -0
  133. data/lib/decidim/decidim_geo/api.rb +23 -0
  134. data/lib/decidim/decidim_geo/engine.rb +58 -0
  135. data/lib/decidim/decidim_geo/load_shp/app_load_shp.rb +85 -0
  136. data/lib/decidim/decidim_geo/space_location/assembly_create_command_override.rb +26 -0
  137. data/lib/decidim/decidim_geo/space_location/assembly_form_override.rb +33 -0
  138. data/lib/decidim/decidim_geo/space_location/assembly_update_command_override.rb +21 -0
  139. data/lib/decidim/decidim_geo/space_location/participatory_process_command_override.rb +21 -0
  140. data/lib/decidim/decidim_geo/space_location/participatory_process_form_override.rb +33 -0
  141. data/lib/decidim/decidim_geo/space_location/space_override.rb +15 -0
  142. data/lib/decidim/decidim_geo/test/factories.rb +13 -0
  143. data/lib/decidim/decidim_geo/version.rb +14 -0
  144. data/lib/decidim/decidim_geo.rb +25 -0
  145. data/lib/tasks/decidim_geo_webpacker_tasks.rake +61 -0
  146. metadata +335 -0
data/README.md ADDED
@@ -0,0 +1,172 @@
1
+ <h1 align="center"><img src="https://github.com/octree-gva/meta/blob/main/decidim/static/header.png?raw=true" alt="Decidim - Octree Participatory democracy on a robust and open source solution" /></h1>
2
+ <h4 align="center">
3
+ <a href="https://octreegva.notion.site/Roadmap-Decidim-GEO-f191fcb9e220401f8135514a7bd41aab">Roadmap</a> |
4
+ <a href="https://drive.google.com/file/d/1lfQJumDg0Ic-RZi-R3MM8frYtKN7PB_S/view?usp=sharing">Presentation</a> |
5
+ <a href="https://github.com/octree-gva/decidim-module-geo/issues">Issues</a> <br/>
6
+ <a href="https://www.octree.ch">Octree</a> |
7
+ <a href="https://octree.ch/en/contact-us/">Contact Us</a> |
8
+ <a href="https://blog.octree.ch">Our Blog (FR)</a><br/><br/>
9
+ <a href="https://decidim.org">Decidim</a> |
10
+ <a href="https://docs.decidim.org/en/">Decidim Docs</a> |
11
+ <a href="https://meta.decidim.org">Participatory Governance (meta decidim)</a><br/><br/>
12
+ <a href="https://matrix.to/#/+decidim:matrix.org">Decidim Community (Matrix+Element.io)</a>
13
+ </h4>
14
+ <p align="center">
15
+ <a href="https://participer.lausanne.ch">
16
+ <img
17
+ src="https://github.com/octree-gva/meta/blob/main/decidim/static/participer_lausanne/chip.png?raw=true"
18
+ alt="Lausanne Participe — Une plateforme de participation pour imaginer et réaliser ensemble" />
19
+ </a>
20
+ <a href="https://opencollective.com/voca">
21
+ <img
22
+ src="https://github.com/octree-gva/meta/blob/main/decidim/static/opencollective_chip.png?raw=true"
23
+ alt="Voca – Open-Source SaaS platform for Decidim" />
24
+ </a>
25
+ </p>
26
+
27
+
28
+ # Decidim::Geo
29
+ Have you ever wondered to centralize all the participation in a map? Well, we do and that is the purpose of Decidim GEO.
30
+ Participation on the map, means:
31
+
32
+ * Overview participation: Be able to consult what happens where.
33
+ * Participate: Be able to pin points, select zones, etc. while participating
34
+
35
+ This project is its early stage, and has it is quiet ambicious, we open CO-FUNDING and setup a public Roadmap here: [https://octreegva.notion.site/Roadmap-Decidim-GEO-f191fcb9e220401f8135514a7bd41aab](https://octreegva.notion.site/Roadmap-Decidim-GEO-f191fcb9e220401f8135514a7bd41aab).
36
+
37
+ If you are curious on how it started, [we've made some slide to present the project](https://drive.google.com/file/d/1lfQJumDg0Ic-RZi-R3MM8frYtKN7PB_S/view?usp=sharing).
38
+
39
+
40
+ ## How it works?
41
+
42
+ Postgis can load Shapefiles that can represents anything: neighbourghoods, cities, states, trees, public spaces.
43
+ We use this module to map a shape to an application zone, to be able to geo-references all the participatory processes of the platform. This way we can offer better consultation experience, and open new perspective for participation.
44
+
45
+ <img
46
+ src="https://github.com/octree-gva/meta/blob/main/decidim/static/geo/admin.png?raw=true"
47
+ alt="Administration of the GEO space" />
48
+ <img
49
+ src="https://github.com/octree-gva/meta/blob/main/decidim/static/geo/consult.png?raw=true"
50
+ alt="Administration of the GEO space" />
51
+
52
+
53
+ ## Installation
54
+ This gem supports decidim version `0.26.x` and `0.27.x`.
55
+
56
+ Read the [needed dependancies for `rgeo` gem](https://github.com/rgeo/rgeo?tab=readme-ov-file#dependencies). If you have `libgeos-dev`, be sure you have a postgis database with postgres > 14.0.
57
+
58
+ Add this line to your application's Gemfile:
59
+ ```ruby
60
+ gem "decidim-decidim_geo"
61
+ ```
62
+
63
+ Update your database adapter to postgis adapter (already installed as dependancy of this gem):
64
+ ```
65
+ # config/database.yml
66
+ default: &default
67
+ adapter: postgis
68
+ ```
69
+
70
+ Update your `DATABASE_URL` environment with `postgis://`:
71
+ ```
72
+ DATABASE_URL="postgis://myuser:mypass@localhost/somedatabase"
73
+ ```
74
+
75
+ And then execute:
76
+
77
+ ```bash
78
+ bundle
79
+ bundle exec rails decidim_geo:install:migrations
80
+ bundle exec rails db:migrate
81
+ ```
82
+
83
+ ## Testing
84
+ ```
85
+ bundle exec rake test_app
86
+ ```
87
+
88
+ ## Local development
89
+ First, you need to run an empty database with a decidim dev container which runs nothing.
90
+ ```
91
+ docker-compose down -v --remove-orphans
92
+ docker-compose up -d
93
+ ```
94
+ Once created, you access the decidim container
95
+ ```
96
+ # Get the id of the decidim dev container
97
+ docker ps --format {{.ID}} --filter=label=org.label-schema.name=decidim
98
+ # f16bd5314386
99
+ docker exec -it f16bd5314386 bash
100
+ ```
101
+ You are now in bash, run manually `docker-entrypoint`.
102
+ ```
103
+ # Will check your environment and do migrations if needed
104
+ docker-entrypoint
105
+ ```
106
+ You are now ready to use your container in the way you want for development:
107
+
108
+ * Run a rails server: `bundle exec rails s -b 0.0.0.0`
109
+ * Have live-reload on your assets: `bin/webpack-dev-server`
110
+ * Execute tasks, like `bundle exec rails g migration AddSomeColumn`
111
+ * etc.
112
+ ```
113
+ bundle exec rails s -b 0.0.0.0 # rails server
114
+ bin/webpack-dev-server
115
+ etc.
116
+ ```
117
+
118
+ To stop everything, uses:
119
+ - `docker-compose down` to stop the containers
120
+ - `docker-compose down -v` to stop the containers and remove all previously saved data.
121
+
122
+ ### Debugging
123
+ To debug something on the container:
124
+ 1. Ensure `decidim-app` is running
125
+ ```bash
126
+ docker ps --all
127
+ # CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
128
+ # f16bd5314386 decidim-geo-development-app "sleep infinity" 13 hours ago Up 13 hours 0.0.0.0:3000->3000/tcp, 0.0.0.0:3035->3035/tcp decidim-app <-------- THIS ONE
129
+ # b56adf6404d8 decidim-geo-development-app "bin/webpack-dev-ser…" 54 seconds ago Up 46 seconds 0.0.0.0:3035->3035/tcp decidim-webpacker decidim-installer
130
+ # bc1e912c3d8a postgis/postgis:14-3.3-alpine "docker-entrypoint.s…" 13 hours ago Up 13 hours 0.0.0.0:5432->5432/tcp decidim-module-geo-pg-1
131
+ ```
132
+
133
+ 2. Run `docker exec -it decidim-app bash`
134
+ 3. Run
135
+ - `tail -f $ROOT/log/development.log` to **access logs**
136
+ - `bundle exec rails restart` to **restart rails server AND keeps webpacker running**
137
+ - `cd $ROOT` to access the `development_app`
138
+ - `cd $ROOT/../decidim_module_geo` to access the module directory
139
+
140
+ ### FAQ
141
+
142
+ **I can't see logs on the `decidim-app`?**
143
+ `decidim-app` runs here in development `webpacker-dev-server` AND a puma server, on the same container.
144
+ Thus, we just run both, and only one will be displayed on STDOUT. To see puma log: `docker exec decidim-app tail -f /home/app/decidim/log/development.log`
145
+
146
+ **It takes for ever to pull the image?**
147
+ Try to pull from docker hub before doing your install script. `docker pull hfroger/decidim:0.26.8-dev` can help.
148
+
149
+ **Why must I access to `127.0.0.1` and not `localhost`?**
150
+ `webpack-dev-server` run a websocket server on port 3535, and the rails server needs to connect to it.
151
+ `localhost` won't make the trick, and you need to use a "real" ip, like `127.0.0.1`. [More info](https://stackoverflow.com/a/54102318)
152
+
153
+ ## Contributing
154
+
155
+ We are not yet ready for contributions, but we are working on a goood workflow
156
+
157
+ # Why it's not on MetaDecidim?
158
+ We think Decidim is already over complicated to install and setup. This module uses PosGis extensions on a postgres database, that can be hard to install. We block the proposal to metadecidim until these points are solved:
159
+
160
+ - We have stable release.
161
+ - We have feedbacks from participants that it is actually usefull.
162
+ - We have feedbacks from Decidim's admins that this is actually improving participation.
163
+ - Decidim run primarly on docker, with an updated documentation on installation. (We, at Octree is working on it for a while)
164
+
165
+ ## License
166
+
167
+ This engine is distributed under the [GNU AFFERO GENERAL PUBLIC LICENSE](LICENSE-AGPLv3.txt)
168
+
169
+ <br /><br />
170
+ <p align="center">
171
+ <img src="https://raw.githubusercontent.com/octree-gva/meta/main/decidim/static/octree_and_decidim.png" height="90" alt="Decidim Installation by Octree" />
172
+ </p>
data/Rakefile ADDED
@@ -0,0 +1,119 @@
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_geo:install:migrations")
8
+ end
9
+ end
10
+
11
+ def seed_db(path)
12
+ Dir.chdir(path) do
13
+ system("bundle exec rake db:seed")
14
+ end
15
+ end
16
+
17
+ ##
18
+ # Tasks for test_app
19
+ ##
20
+
21
+ desc "Prepare for testing"
22
+ task :prepare_tests do
23
+ # Remove previous existing db, and recreate one.
24
+ Dir.chdir("development_app") do
25
+ system("bundle exec rake db:drop")
26
+ system("bundle exec rake db:create")
27
+ end
28
+ ENV["RAILS_ENV"] = "test"
29
+ databaseYml = {
30
+ "test" => {
31
+ "adapter" => "postgis",
32
+ "encoding" => "unicode",
33
+ "host" => ENV.fetch("DATABASE_HOST", "localhost"),
34
+ "port" => ENV.fetch("DATABASE_PORT", "5432").to_i,
35
+ "username" => ENV.fetch("DATABASE_USERNAME", "decidim"),
36
+ "password" => ENV.fetch("DATABASE_PASSWORD", "insecure-password"),
37
+ "database" => "#{base_app_name}_test"
38
+ }
39
+ }
40
+ config_file = File.expand_path("spec/decidim_dummy_app/config/database.yml", __dir__)
41
+ File.open(config_file, "w") { |f| YAML.dump(databaseYml, f) }
42
+ Dir.chdir("spec/decidim_dummy_app") do
43
+ system("bundle exec rails db:migrate")
44
+ end
45
+ end
46
+
47
+ desc "Generates a decidim_dummy_app app for testing"
48
+ task :test_app do
49
+ Bundler.with_original_env do
50
+ generate_decidim_app(
51
+ "spec/decidim_dummy_app",
52
+ "--app_name",
53
+ "#{base_app_name}",
54
+ "--path",
55
+ "../..",
56
+ "--skip_spring",
57
+ "--demo",
58
+ "--force_ssl",
59
+ "false",
60
+ "--locales",
61
+ "en,fr,es"
62
+ )
63
+ end
64
+ install_module("spec/decidim_dummy_app")
65
+ Rake::Task["prepare_tests"].invoke
66
+ end
67
+
68
+ ##
69
+ # Tasks for developement_app
70
+ ##
71
+
72
+ desc "Prepare for development"
73
+ task :prepare_dev do
74
+ # Remove previous existing db, and recreate one.
75
+ Dir.chdir("development_app") do
76
+ system("bundle exec rake db:drop")
77
+ system("bundle exec rake db:create")
78
+ end
79
+ ENV["RAILS_ENV"] = "development"
80
+ databaseYml = {
81
+ "development" => {
82
+ "adapter" => "postgis",
83
+ "encoding" => "unicode",
84
+ "host" => ENV.fetch("DATABASE_HOST", "localhost"),
85
+ "port" => ENV.fetch("DATABASE_PORT", "5432").to_i,
86
+ "username" => ENV.fetch("DATABASE_USERNAME", "decidim"),
87
+ "password" => ENV.fetch("DATABASE_PASSWORD", "insecure-password"),
88
+ "database" => "#{base_app_name}_development",
89
+ }
90
+ }
91
+ config_file = File.expand_path("development_app/config/database.yml", __dir__)
92
+ File.open(config_file, "w") { |f| YAML.dump(databaseYml, f) }
93
+ Dir.chdir("development_app") do
94
+ system("bundle exec rake db:migrate")
95
+ system("npm install -D webpack-dev-server")
96
+ end
97
+ end
98
+
99
+ desc "Generates a development app"
100
+ task :development_app do
101
+ Bundler.with_original_env do
102
+ generate_decidim_app(
103
+ "development_app",
104
+ "--app_name",
105
+ "#{base_app_name}",
106
+ "recreate_db",
107
+ "--path",
108
+ "..",
109
+ "--skip_spring",
110
+ "--demo",
111
+ "--force_ssl",
112
+ "false",
113
+ "--demo"
114
+ )
115
+ end
116
+
117
+ install_module("development_app")
118
+ Rake::Task["prepare_dev"].invoke
119
+ end
@@ -0,0 +1,15 @@
1
+ <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.2/dist/leaflet.css" integrity="sha256-sA+zWATbFveLLNqWO2gtiw3HL/lh1giY/Inf1BJ0z14=" crossorigin="">
2
+ <script src="https://unpkg.com/leaflet@1.9.2/dist/leaflet.js" integrity="sha256-o9N1jGDZrf5tS+Ft4gbIK7mYMipq9lqpVJ91xHSyKhg=" crossorigin=""></script>
3
+
4
+ <style>
5
+ .decidimgeo__map {
6
+ height: 640px;
7
+ width: 100%;
8
+ max-width: 100%;
9
+ max-height: 100%;
10
+ }
11
+ </style>
12
+
13
+ <%= javascript_pack_tag "decidim_geo" %>
14
+
15
+ <%= insert_map %>
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Geo
5
+ module ContentBlocks
6
+ class GeoMapsCell < Decidim::ViewModel
7
+ #delegate :current_user, to: :controller
8
+ include Decidim::SanitizeHelper
9
+
10
+ def show
11
+ render unless @options.empty?
12
+ end
13
+
14
+ private
15
+
16
+ def insert_map
17
+ id = @options[:id] || "HomePage"
18
+ filters = @options[:filters] || []
19
+ config = {
20
+ locale: current_locale,
21
+ space_ids: @options[:scopes] || [],
22
+ selected_component: current_component || nil,
23
+ selected_point: current_component? && params[:id] ? params[:id] : nil,
24
+ images: {
25
+ not_geolocated: ActionController::Base.helpers.asset_pack_path("media/images/not-geolocated.svg")
26
+ },
27
+ filters: @options[:filters] || [],
28
+ map_config: {
29
+ lat: geo_config[:latitude],
30
+ lng: geo_config[:longitude],
31
+ tile_layer: geo_config[:tile],
32
+ zoom: geo_config[:zoom]
33
+ }
34
+ }.with_indifferent_access
35
+
36
+ content_tag(
37
+ :div,
38
+ '',
39
+ id: "DecidimGeo",
40
+ class: [
41
+ "js-decidimgeo",
42
+ "decidimgeo__map",
43
+ "decidimgeo__map--#{id.underscore}"
44
+ ],
45
+ "data-config" => config.to_json,
46
+ "data-i18n" => geo_i18n.to_json
47
+ )
48
+ end
49
+
50
+ def geo_i18n
51
+ supported_models = [
52
+ Decidim::Meetings::Meeting,
53
+ Decidim::Proposals::Proposal,
54
+ Decidim::ParticipatoryProcess,
55
+ Decidim::Assembly,
56
+ Decidim::Debates::Debate
57
+ ]
58
+ geo_i18n = supported_models.map { |klass| [klass.name, klass.model_name.human] }.to_h
59
+ geo_i18n = {
60
+ **geo_i18n,
61
+ "decidim_geo.scopes.all": t('decidim.geo.scopes.all'),
62
+ "decidim_geo.scopes.dropdown": t('decidim.geo.scopes.dropdown'),
63
+ "decidim_geo.filters.back": t('decidim.geo.filters.back'),
64
+ "decidim_geo.filters.button": t('decidim.geo.filters.button'),
65
+ "decidim_geo.filters.geo.label": t('decidim.geo.filters.geo.label'),
66
+ "decidim_geo.filters.geo.all": t('decidim.geo.filters.geo.all'),
67
+ "decidim_geo.filters.geo.only_geoencoded": t('decidim.geo.filters.geo.only_geoencoded'),
68
+ "decidim_geo.filters.geo.only_virtual": t('decidim.geo.filters.geo.only_virtual'),
69
+ "decidim_geo.filters.time.label": t('decidim.geo.filters.time.label'),
70
+ "decidim_geo.filters.time.all": t('decidim.geo.filters.time.all'),
71
+ "decidim_geo.filters.time.only_past": t('decidim.geo.filters.time.only_past'),
72
+ "decidim_geo.filters.time.only_active": t('decidim.geo.filters.time.only_active'),
73
+ "decidim_geo.filters.time.only_future": t('decidim.geo.filters.time.only_future'),
74
+ "decidim_geo.filters.type.label": t('decidim.geo.filters.type.label'),
75
+ "decidim_geo.filters.type.all": t('decidim.geo.filters.type.all'),
76
+ "decidim_geo.filters.type.only_processes": t('decidim.geo.filters.type.only_processes'),
77
+ "decidim_geo.filters.type.only_assemblies": t('decidim.geo.filters.type.only_assemblies'),
78
+ "decidim_geo.filters.type.only_proposals": t('decidim.geo.filters.type.only_proposals'),
79
+ "decidim_geo.filters.type.only_meetings": t('decidim.geo.filters.type.only_meetings'),
80
+
81
+ }
82
+ end
83
+
84
+
85
+ def current_locale
86
+ I18n.locale.to_s
87
+ end
88
+
89
+ def current_component
90
+ return request.env["decidim.current_component"].id if current_component?
91
+ "none"
92
+ end
93
+
94
+ def current_component?
95
+ request.env["decidim.current_component"].present?
96
+ end
97
+
98
+ def geo_config
99
+ {
100
+ latitude: model.try(:latitude).nil? ? geo_config_default.latitude : model.latitude,
101
+ longitude: model.try(:longitude).nil? ? geo_config_default.longitude: model.longitude,
102
+ tile: Decidim::Geo::GeoConfig.geo_config_default.tile,
103
+ zoom: Decidim::Geo::GeoConfig.geo_config_default.zoom
104
+ }.to_h
105
+ end
106
+
107
+ def geo_config_default
108
+ Decidim::Geo::GeoConfig.geo_config_default
109
+ end
110
+
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,14 @@
1
+ module Decidim
2
+ module Geo
3
+ module ContentBlocks
4
+ class GeoMapsSettingsFormCell < Decidim::ViewModel
5
+ alias form model
6
+
7
+ def content_block
8
+ options[:content_block]
9
+ end
10
+
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,4 @@
1
+ <%
2
+ # cell("decidim/geo/content_blocks/geo_maps", nil, **search_options) if search_controller?
3
+ %>
4
+ <%= cell("decidim/geo/content_blocks/geo_maps", nil, **collection_options) if participatory_space? %>
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Geo
5
+ class GeoCollectionMapCell < Decidim::ViewModel
6
+ delegate :current_user, to: :controller
7
+ include Decidim::SanitizeHelper
8
+
9
+ def show
10
+ render
11
+ end
12
+
13
+ private
14
+ def participatory_space?
15
+ [
16
+ "decidim/assemblies/assemblies:index",
17
+ "decidim/participatory_processes/participatory_processes:index"
18
+ ].include? "#{params[:controller]}:#{params[:action]}"
19
+ end
20
+
21
+ def search_controller?
22
+ params[:controller] == "decidim/searches"
23
+ end
24
+
25
+ def search_options
26
+ param_filter = params[:filter]
27
+ return {} if param_filter.nil?
28
+ param_filter.permit!
29
+ filters = param_filter.keys.map do |key|
30
+ case "#{key}"
31
+ when "resource_type"
32
+ {resourceTypeFilter: {resourceType: param_filter[key]}}
33
+ when "term"
34
+ {termFilter: {term: param_filter[key]}}
35
+ when "decidim_scope_id"
36
+ {scopeFilter: {scopeId: [param_filter[key]]}}
37
+ when "space_state"
38
+ {termFilter: {space_state: param_filter[key]}}
39
+ end
40
+ end.select {|v| !v.nil?}
41
+ {
42
+ id: "Search",
43
+ filters: filters,
44
+ scopes: []
45
+ }
46
+ end
47
+
48
+ def collection_options
49
+ case "#{params[:controller]}:#{params[:action]}"
50
+ when "decidim/assemblies/assemblies:index"
51
+ {
52
+ id: "Assemblies",
53
+ filters: assemblies_filter,
54
+ scopes: assemblies_scopes
55
+ }
56
+ when "decidim/participatory_processes/participatory_processes:index"
57
+ {
58
+ id: "Processes",
59
+ filters: processes_filter,
60
+ scopes: processes_scopes
61
+ }
62
+ else
63
+ {}
64
+ end
65
+ end
66
+
67
+ def visible_processes
68
+ Decidim::ParticipatoryProcess.visible_for(
69
+ current_user
70
+ )
71
+ end
72
+ def processes_scopes
73
+ visible_processes.map { |a| a.scopes.map{ |s| s.id} }.flatten.uniq
74
+ end
75
+ def visible_assemblies
76
+ Decidim::Assembly.visible_for(
77
+ current_user
78
+ )
79
+ end
80
+ def assemblies_scopes
81
+ visible_assemblies.map { |a| a.scopes.map{ |s| s.id} }.flatten.uniq
82
+ end
83
+
84
+ def assemblies_filter
85
+ return [{resourceTypeFilter: {resourceType: "Decidim::Assembly"}}] if geo_config.only_assemblies
86
+ # Filter only content that are bound to one of the displayed assemblies
87
+ visible_assemblies.map {|assembly| {assemblyFilter: {assemblyId: assembly.id}} }
88
+ end
89
+
90
+ def processes_filter
91
+ return [{resourceTypeFilter: {resourceType: "Decidim::ParticipatoryProcess"}}] if geo_config.only_processes
92
+ # Filter only content that are bound to one of the displayed processes
93
+ visible_processes.map {|process| {processFilter: {processId: process.id}} }
94
+ end
95
+
96
+ def geo_config
97
+ Decidim::Geo::GeoConfig.geo_config_default
98
+ end
99
+ end
100
+ end
101
+ end
102
+
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ # A command with all the business logic when creating a static scope.
6
+ class CreateScope < Decidim::Geo::Command
7
+ # Public: Initializes the command.
8
+ #
9
+ # form - A form object with the params.
10
+ # parent_scope - A parent scope for the scope to be created
11
+ def initialize(form, parent_scope = nil)
12
+ @form = form
13
+ @parent_scope = parent_scope
14
+ end
15
+
16
+ # Executes the command. Broadcasts these events:
17
+ #
18
+ # - :ok when everything is valid.
19
+ # - :invalid if the form wasn't valid and we couldn't proceed.
20
+ #
21
+ # Returns nothing.
22
+ def call
23
+ return broadcast(:invalid) if form.invalid?
24
+
25
+ scope = create_scope
26
+ broadcast(:ok, :scope=>scope)
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :form
32
+
33
+ def create_scope
34
+ Decidim.traceability.create!(
35
+ Scope,
36
+ form.current_user,
37
+ {
38
+ name: form.name,
39
+ organization: form.organization,
40
+ code: form.code,
41
+ scope_type: form.scope_type,
42
+ parent: @parent_scope
43
+ },
44
+ extra: {
45
+ parent_name: @parent_scope.try(:name),
46
+ scope_type_name: form.scope_type.try(:name)
47
+ }
48
+ )
49
+ end
50
+
51
+ def shapedata
52
+ Decidim::Geo::Shapedata.find_by_id(form.shapedata)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ # A command with all the business logic when creating a scope type.
6
+ class CreateScopeType < Decidim::Geo::Command
7
+ # Public: Initializes the command.
8
+ #
9
+ # form - A form object with the params.
10
+ def initialize(form, user = nil)
11
+ @form = form
12
+ @user = user
13
+ end
14
+
15
+ # Executes the command. Broadcasts these events:
16
+ #
17
+ # - :ok when everything is valid.
18
+ # - :invalid if the form wasn't valid and we couldn't proceed.
19
+ #
20
+ # Returns nothing.
21
+ def call
22
+ return broadcast(:invalid) if form.invalid?
23
+
24
+ create_scope_type
25
+ broadcast(:ok)
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :form
31
+
32
+ def create_scope_type
33
+ scope_type = ScopeType.create!(
34
+ name: form.name,
35
+ organization: form.organization,
36
+ plural: form.plural
37
+ )
38
+ scope_type.shapefile = shapefile
39
+ scope_type.save!
40
+ end
41
+
42
+ def shapefile
43
+ Decidim::Geo::Shapefile.find_by_id(form.shapefile)
44
+ end
45
+ end
46
+ end
47
+ end