decidim-decidim_awesome 0.6.6 → 0.6.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -0
  3. data/app/assets/javascripts/decidim/decidim_awesome/admin.js +1 -0
  4. data/app/assets/javascripts/decidim/decidim_awesome/admin/codemirror.js.es6 +15 -0
  5. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/hashtags.js.es6 +48 -0
  6. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/layers.js.es6 +106 -0
  7. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/legacy_map.js.es6 +12 -19
  8. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/legacy_proposals.js.es6 +3 -2
  9. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/map.js.es6 +166 -170
  10. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/markers.js.es6 +56 -0
  11. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/meetings.js.es6 +4 -3
  12. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/proposals.js.es6 +17 -4
  13. data/app/assets/javascripts/decidim/decidim_awesome/awesome_map/utilities.js.es6 +48 -0
  14. data/app/assets/stylesheets/decidim/decidim_awesome/admin.scss +7 -4
  15. data/app/assets/stylesheets/decidim/decidim_awesome/admin/codemirror.scss +16 -0
  16. data/app/assets/stylesheets/decidim/decidim_awesome/awesome_map/leaflet.scss.erb +9 -0
  17. data/app/assets/stylesheets/decidim/decidim_awesome/awesome_map/map.scss +95 -0
  18. data/app/assets/stylesheets/decidim/decidim_awesome/editors/markdown_editor.scss +1 -1
  19. data/app/commands/decidim/decidim_awesome/admin/update_config.rb +4 -1
  20. data/app/controllers/decidim/decidim_awesome/admin/config_controller.rb +2 -2
  21. data/app/forms/decidim/decidim_awesome/admin/config_form.rb +11 -0
  22. data/app/helpers/decidim/decidim_awesome/map_helper.rb +9 -3
  23. data/app/views/decidim/decidim_awesome/admin/config/_form_styles.html.erb +1 -0
  24. data/app/views/decidim/decidim_awesome/admin/config/show.html.erb +1 -2
  25. data/app/views/decidim/decidim_awesome/map_component/map/show.html.erb +9 -6
  26. data/app/views/layouts/decidim/decidim_awesome/_awesome_config.html.erb +4 -1
  27. data/config/locales/ca.yml +13 -0
  28. data/config/locales/cs.yml +13 -0
  29. data/config/locales/en.yml +14 -0
  30. data/config/locales/es.yml +13 -0
  31. data/config/locales/eu.yml +13 -0
  32. data/config/locales/fr.yml +154 -141
  33. data/config/locales/nl.yml +148 -135
  34. data/config/locales/sv.yml +47 -34
  35. data/lib/decidim/decidim_awesome/map_component/component.rb +7 -1
  36. data/lib/decidim/decidim_awesome/version.rb +1 -1
  37. data/vendor/assets/javascripts/codemirror.js +9801 -0
  38. data/vendor/assets/javascripts/jquery.truncate.js +105 -0
  39. data/vendor/assets/javascripts/keymap/sublime.js +720 -0
  40. data/vendor/assets/javascripts/mode/css/css.js +864 -0
  41. data/vendor/assets/stylesheets/codemirror.css +350 -0
  42. data/vendor/assets/stylesheets/inscrybmde.min.scss +180 -0
  43. metadata +28 -3
  44. data/vendor/assets/stylesheets/inscrybmde.min.css +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f080eae1f34847934c143b7bdc9c091632701cb339f269754640d5f2a78f879
4
- data.tar.gz: 64f8f793914cf99e2f5ac37801039000936911799c518da44528698f6c3fba92
3
+ metadata.gz: 32cc1fc0147bd8a5daf75a5deab25f18ede902f0ceb8c9a4a0073528dec97568
4
+ data.tar.gz: 2ed32bdc25c0e2ab7b5b8b7362adad7a191634290b896e6f3e0f630687ba0824
5
5
  SHA512:
6
- metadata.gz: 507f43c02cfe83261c5e0caa656387aba8dc7ffa15a80c70305e71736e1aeebec90a6678f663ca4de854740f17ef2960a29f9d58caf980e1c0dbd534b1d0c46b
7
- data.tar.gz: 7398b5cacb4eed3ff628a7026c2934c089dcbe8b1cf9ff9cd22275228816fa1ddc9ba50909dbf4bccf4e0e671349517c8bea4485e8c3dd709868f17000ef55a2
6
+ metadata.gz: df2b4b28994f8ad2f11e87080c683edb9fc8f215c76a7b6e15ebd27df018317fb64daf5f1c9b3910d2bd6c676d746caadec6defdaeb57716509cb9b3b33b67d8
7
+ data.tar.gz: 95a51e3cf9e87c8b2c9756ad6ab11ab1ee90d252b16f99740a20e190742bb0017e88bb36357ac2031d588bcf792b86d1337fe0685c7dfb309789beb4a7aa6797
data/README.md CHANGED
@@ -160,6 +160,8 @@ admins do not even see it.
160
160
 
161
161
  In order to personalize default values, create an initializer such as:
162
162
 
163
+ > **NOTE**: this is not necessary unless you want to **disable** some features. All features are enabled by default.
164
+
163
165
  ```ruby
164
166
  # config/initializers/awesome_defaults.rb
165
167
 
@@ -173,6 +175,9 @@ Decidim::DecidimAwesome.configure do |config|
173
175
 
174
176
  # De-activated, admins don't even see it as an option
175
177
  config.use_markdown_editor = :disabled
178
+
179
+ # any other config var from lib/decidim/decidim_awesome.rb
180
+ ...
176
181
  end
177
182
  ```
178
183
 
@@ -1,2 +1,3 @@
1
1
  // = require decidim/decidim_awesome/admin/constraints
2
+ // = require decidim/decidim_awesome/admin/codemirror
2
3
  // = require decidim/decidim_awesome/editors/quill_editor
@@ -0,0 +1,15 @@
1
+ // = require codemirror
2
+ // = require mode/css/css
3
+ // = require keymap/sublime
4
+ // = require_self
5
+
6
+ $(() => {
7
+ $(".awesome-edit-config .scoped-style textarea").each((_idx, el) => {
8
+ console.log(el)
9
+ var editor = CodeMirror.fromTextArea(el, {
10
+ lineNumbers: true,
11
+ mode: "css",
12
+ keymap: "sublime"
13
+ });
14
+ })
15
+ });
@@ -0,0 +1,48 @@
1
+ ((exports) => {
2
+ const hashtags = [];
3
+
4
+ const collectHashtags = (text) => {
5
+ let tags = [];
6
+ if(text) {
7
+ const gids = text.match(/gid:\/\/[^\s<]+/g)
8
+ if(gids) {
9
+ tags = gids.filter(gid => gid.indexOf("/Decidim::Hashtag/") != -1).map(gid => {
10
+ const parts = gid.split("/");
11
+ const fromSelector = parts[5].charAt(0) == '_';
12
+ const tag = fromSelector ? parts[5].substr(1) : parts[5];
13
+ const name = '#' + tag;
14
+ const html = `<a href="/search?term=${name}">${name}</a>`;
15
+ const hashtag = {
16
+ color: getComputedStyle(document.documentElement).getPropertyValue('--secondary'),
17
+ gid: gid,
18
+ id: parseInt(parts[4], 10),
19
+ fromSelector: fromSelector,
20
+ tag: tag,
21
+ name: name,
22
+ html: html
23
+ }
24
+ hashtags.push(hashtag)
25
+ return hashtag;
26
+ });
27
+ }
28
+ }
29
+ return tags;
30
+ };
31
+
32
+ const removeHashtags = (text) => {
33
+ return text.replace(/gid:\/\/[^\s<]+/g, "");
34
+ };
35
+
36
+ const appendHtmlHashtags = (text, tags) => {
37
+ tags.forEach(tag => {
38
+ text += ` ${tag.html}`;
39
+ });
40
+ return text;
41
+ };
42
+
43
+ exports.AwesomeMap = exports.AwesomeMap || {};
44
+ exports.AwesomeMap.hashtags = hashtags;
45
+ exports.AwesomeMap.collectHashtags = collectHashtags;
46
+ exports.AwesomeMap.appendHtmlHashtags = appendHtmlHashtags;
47
+ exports.AwesomeMap.removeHashtags = removeHashtags;
48
+ })(window);
@@ -0,0 +1,106 @@
1
+ // = require leaflet.featuregroup.subgroup
2
+ // = require decidim/decidim_awesome/awesome_map/utilities
3
+ // = require decidim/decidim_awesome/awesome_map/categories
4
+ // = require decidim/decidim_awesome/awesome_map/hashtags
5
+
6
+ ((exports) => {
7
+ const { collapsedMenu, options, categories } = exports.AwesomeMap;
8
+ const layers = {};
9
+ const cluster = L.markerClusterGroup();
10
+
11
+ const control = L.control.layers(null, null, {
12
+ position: 'topleft',
13
+ sortLayers: false,
14
+ collapsed: collapsedMenu,
15
+ // hideSingleBase: true
16
+ });
17
+
18
+ const addProposalsControls = (map, component) => {
19
+ // add control layer for proposals
20
+ layers.proposals = {
21
+ label: `<span class="awesome_map-component" id="awesome_map-component_${component.id}" title="0">${component.name || window.DecidimAwesome.texts.proposals}</span>`,
22
+ group: L.featureGroup.subGroup(cluster)
23
+ };
24
+ control.addOverlay(layers.proposals.group, layers.proposals.label);
25
+ layers.proposals.group.addTo(map);
26
+
27
+ // add control layer for amendments if any
28
+ if(options.menu.amendments && component.amendments) {
29
+ layers.amendments = {
30
+ label: `<span class="awesome_map-component" id="awesome_map-amendments_${component.id}" title="0">${window.DecidimAwesome.texts.amendments}</span>`,
31
+ group: L.featureGroup.subGroup(cluster)
32
+ }
33
+ control.addOverlay(layers.amendments.group, layers.amendments.label);
34
+ layers.amendments.group.addTo(map);
35
+ }
36
+ };
37
+
38
+ const addMeetingsControls = (map, component) => {
39
+ // add control layer for meetings
40
+ layers.meetings = {
41
+ label: `<span class="awesome_map-component" id="awesome_map-component_${component.id}" title="0">${component.name || window.DecidimAwesome.texts.meetings}</span>`,
42
+ group: L.featureGroup.subGroup(cluster)
43
+ };
44
+ control.addOverlay(layers.meetings.group, layers.meetings.label);
45
+ layers.meetings.group.addTo(map);
46
+ };
47
+
48
+ const addSearchControls = () => {
49
+ $(control.getContainer()).contents("form").after(`<div id="awesome_map-categories-control" class="active"><b class="awesome_map-title-control">${window.DecidimAwesome.texts.categories}</b><div class="categories-container"></div></div>
50
+ <div id="awesome_map-hashtags-control"><b class="awesome_map-title-control">${window.DecidimAwesome.texts.hashtags}</b><div class="hashtags-container"></div><a href="#" class="awesome_map-toggle_all_tags">${window.DecidimAwesome.texts.select_deselect_all}</a></div>`);
51
+ };
52
+
53
+ const addCategoriesControls = (map) => {
54
+ if(categories && categories.length) {
55
+ categories.forEach((category) => {
56
+ // add control layer for this category
57
+ const label = `<i class="awesome_map-category-${category.id}"></i> ${category.name}`;
58
+ layers[category.id] = {
59
+ label: label,
60
+ group: L.featureGroup.subGroup(cluster)
61
+ };
62
+ layers[category.id].group.addTo(map);
63
+ // In the next iteration to be sure layers are rendered
64
+ setTimeout(() => {
65
+ $('#awesome_map-categories-control .categories-container').append(`<label data-layer="${category.id}" class="awesome_map-category-${category.id}${category.parent?" subcategory":""}"><input type="checkbox" class="awesome_map-categories-selector" checked><span>${label}</span></label>`);
66
+ });
67
+ });
68
+ }
69
+ };
70
+
71
+ // Hashtags are collected directly from proposals (this is different than categories)
72
+ const addHashtagsControls = (map, hashtags, marker) => {
73
+ // show hashtag layer
74
+ if(hashtags && hashtags.length) {
75
+ $('#awesome_map-hashtags-control').show();
76
+ hashtags.forEach(hashtag => {
77
+ // Add layer if not exists, otherwise just add the marker to the group
78
+ if(!layers[hashtag.tag]) {
79
+ layers[hashtag.tag] = {
80
+ label: hashtag.name,
81
+ group: L.featureGroup.subGroup(cluster)
82
+ };
83
+ layers[hashtag.tag].group.addTo(map);
84
+ $('#awesome_map-hashtags-control .hashtags-container').append(`<label data-layer="${hashtag.tag}" class="awesome_map-hashtag-${hashtag.tag}"><input type="checkbox" class="awesome_map-hashtags-selector" checked><span>${hashtag.name}</span></label>`);
85
+ // Call a trigger, might be in service for customizations
86
+ exports.AwesomeMap.hashtagAdded(hashtag, $('#awesome_map-hashtags-control .hashtags-container'));
87
+ }
88
+ marker.addTo(layers[hashtag.tag].group);
89
+
90
+ const $label = $(`label.awesome_map-hashtag-${hashtag.tag}`);
91
+ // update number of items
92
+ $label.attr("title", (parseInt($label.attr("title") || 0) + 1) + " " + window.DecidimAwesome.texts.items);
93
+ });
94
+ }
95
+ };
96
+
97
+ exports.AwesomeMap.layers = layers;
98
+ exports.AwesomeMap.control = control;
99
+ exports.AwesomeMap.cluster = cluster;
100
+ exports.AwesomeMap.addProposalsControls = addProposalsControls;
101
+ exports.AwesomeMap.addMeetingsControls = addMeetingsControls;
102
+ exports.AwesomeMap.addSearchControls = addSearchControls;
103
+ exports.AwesomeMap.addCategoriesControls = addCategoriesControls;
104
+ exports.AwesomeMap.addHashtagsControls = addHashtagsControls;
105
+ exports.AwesomeMap.hashtagAdded = $.noop;
106
+ })(window);
@@ -1,13 +1,14 @@
1
1
  // = require jsrender.min
2
2
  // = require decidim/map
3
3
  // = require leaflet.featuregroup.subgroup
4
+ // = require decidim/decidim_awesome/awesome_map/utilities
4
5
  // = require decidim/decidim_awesome/awesome_map/categories
5
6
  // = require decidim/decidim_awesome/awesome_map/legacy_proposals
6
7
  // = require decidim/decidim_awesome/awesome_map/meetings
7
8
  // = require_self
8
9
 
9
10
  ((exports) => {
10
- const { fetchProposals, fetchMeetings, getCategory } = exports.AwesomeMap;
11
+ const { fetchProposals, fetchMeetings, getCategory, amendments } = exports.AwesomeMap;
11
12
 
12
13
  const collapsedMenu = $("#map").data("collapsed");
13
14
  const show = {
@@ -22,14 +23,12 @@
22
23
  const popupProposalTemplateId = "legacy-marker-proposal-popup";
23
24
 
24
25
  const cluster = L.markerClusterGroup();
25
- const amendments = [];
26
-
27
26
  const layers = {};
28
27
 
29
28
  const control = L.control.layers(null, null, {
30
- position: 'topleft',
29
+ position: 'topleft',
31
30
  sortLayers: false,
32
- collapsed: collapsedMenu,
31
+ collapsed: collapsedMenu,
33
32
  // hideSingleBase: true
34
33
  });
35
34
  const allMarkers = [];
@@ -39,26 +38,20 @@
39
38
  node = document.createElement("div");
40
39
 
41
40
  $($.templates(`#${tmpl}`).render(element)).appendTo(node);
42
-
41
+
43
42
  marker.bindPopup(node, {
44
43
  maxwidth: 640,
45
44
  minWidth: 500,
46
45
  keepInView: true,
47
46
  className: "map-info"
48
47
  }).openPopup();
49
-
48
+
50
49
  allMarkers.push({
51
50
  marker: marker,
52
51
  component: component,
53
52
  element: element
54
53
  });
55
54
 
56
- // Check if it has amendments, add it to a list
57
- if(element.amendments && element.amendments.length) {
58
- element.amendments.forEach((amendment) => {
59
- amendments.push(amendment.emendation.id);
60
- });
61
- }
62
55
  // Add to category layer
63
56
  let cat = getCategory(element.category);
64
57
  if(layers[cat.id]) {
@@ -86,7 +79,7 @@
86
79
  cluster.addTo(map);
87
80
 
88
81
  // Load markers
89
- components.forEach((component) => {
82
+ components.forEach((component) => {
90
83
  if(component.type == "proposals") {
91
84
  // add control layer for proposals
92
85
  layers.proposals = {
@@ -108,7 +101,7 @@
108
101
 
109
102
  fetchProposals(component, '', (element, marker) => {
110
103
  if(show[element.state || 'notAnswered']) {
111
- drawMarker(element, marker, component).addTo(layers.proposals.group)
104
+ drawMarker(element, marker, component).addTo(layers.proposals.group)
112
105
  }
113
106
  }, () => {
114
107
  // finall call
@@ -122,7 +115,7 @@
122
115
  });
123
116
  });
124
117
  }
125
-
118
+
126
119
  if(component.type == "meetings") {
127
120
  // add control layer for meetings
128
121
  layers.meetings = {
@@ -131,7 +124,7 @@
131
124
  };
132
125
  control.addOverlay(layers.meetings.group, layers.meetings.label);
133
126
  layers.meetings.group.addTo(map);
134
-
127
+
135
128
  fetchMeetings(component, '', (element, marker) => {
136
129
  drawMarker(element, marker, component).addTo(layers.meetings.group);
137
130
  }, () => {
@@ -167,12 +160,12 @@
167
160
 
168
161
  // watch events for subcategories syncronitzation
169
162
  const getCatFromClass = (name) => {
170
- let id = name.match(/awesome_map-category_(\d+)/)
163
+ let id = name.match(/awesome_map-category_(\d+)/)
171
164
  if(!id) return;
172
165
  const cat = getCategory(id[1]);
173
166
  if(!cat || !cat.name) return;
174
167
 
175
- return cat;
168
+ return cat;
176
169
  };
177
170
 
178
171
  const indeterminateInput = (id) => {
@@ -1,8 +1,9 @@
1
1
  // = require decidim/decidim_awesome/awesome_map/api_fetcher
2
2
  // = require decidim/decidim_awesome/awesome_map/categories
3
+ // = require decidim/decidim_awesome/awesome_map/utilities
3
4
 
4
5
  ((exports) => {
5
- const { getCategory } = exports.AwesomeMap;
6
+ const { getCategory, truncate } = exports.AwesomeMap;
6
7
  const query = `query ($id: ID!, $after: String!) {
7
8
  component(id: $id) {
8
9
  id
@@ -48,7 +49,7 @@
48
49
  })
49
50
  });
50
51
 
51
- element.body = element.body.replace(/\n/g, "<br>");
52
+ element.body = truncate(element.body.replace(/\n/g, "<br>"));
52
53
  callback(element, marker);
53
54
  };
54
55
 
@@ -1,82 +1,41 @@
1
- // = require jsrender.min
2
- // = require leaflet.featuregroup.subgroup
1
+ // = require decidim/decidim_awesome/awesome_map/layers
2
+ // = require decidim/decidim_awesome/awesome_map/utilities
3
+ // = require decidim/decidim_awesome/awesome_map/markers
3
4
  // = require decidim/decidim_awesome/awesome_map/categories
4
5
  // = require decidim/decidim_awesome/awesome_map/proposals
5
6
  // = require decidim/decidim_awesome/awesome_map/meetings
6
7
  // = require_self
7
8
 
8
9
  ((exports) => {
9
- const { fetchProposals, fetchMeetings, getCategory } = exports.AwesomeMap;
10
-
11
- const collapsedMenu = $("#awesome-map").data("collapsed");
12
- const show = {
13
- withdrawn: $("#awesome-map").data("show-withdrawn"),
14
- accepted: $("#awesome-map").data("show-accepted"),
15
- evaluating: $("#awesome-map").data("show-evaluating"),
16
- notAnswered: $("#awesome-map").data("show-not-answered"),
17
- rejected: $("#awesome-map").data("show-rejected")
18
- };
19
- const components = $("#awesome-map").data("components");
20
- const popupMeetingTemplateId = "marker-meeting-popup";
21
- const popupProposalTemplateId = "marker-proposal-popup";
22
-
23
- const cluster = L.markerClusterGroup();
24
- const amendments = [];
25
-
26
- const layers = {};
27
-
28
- const control = L.control.layers(null, null, {
29
- position: 'topleft',
30
- sortLayers: false,
31
- collapsed: collapsedMenu,
32
- // hideSingleBase: true
33
- });
34
- const allMarkers = [];
35
-
36
- const drawMarker = (element, marker, component) => {
37
- let tmpl = component.type === "proposals" ? popupProposalTemplateId : popupMeetingTemplateId,
38
- node = document.createElement("div");
39
-
40
- $($.templates(`#${tmpl}`).render(element)).appendTo(node);
41
-
42
- marker.bindPopup(node, {
43
- maxwidth: 640,
44
- minWidth: 500,
45
- keepInView: true,
46
- className: "map-info"
47
- }).openPopup();
48
-
49
- allMarkers.push({
50
- marker: marker,
51
- component: component,
52
- element: element
53
- });
54
-
55
- // Check if it has amendments, add it to a list
56
- if(element.amendments && element.amendments.length) {
57
- element.amendments.forEach((amendment) => {
58
- amendments.push(amendment.emendation.id);
59
- });
60
- }
61
- // Add to category layer
62
- let cat = getCategory(element.category);
63
- if(layers[cat.id]) {
64
- marker.addTo(layers[cat.id].group);
65
- // show category if hidden
66
- const $label = $(`.awesome_map-category_${cat.id}`).closest("label");
67
- const $parent = $(`.awesome_map-category_${cat.parent}`).closest("label");
68
- $label.show();
69
- // update number of items
70
- $label.attr("title", parseInt($label.attr("title") || 0) + 1);
71
- // show parent if apply
72
- $parent.show();
73
- $parent.attr("title", parseInt($parent.attr("title") || 0) + 1);
74
- // update component stats
75
- const $component = $(`#awesome_map-component-${component.id}`);
76
- $component.attr("title", parseInt($component.attr("title") || 0) + 1);
10
+ const {
11
+ layers,
12
+ cluster,
13
+ control,
14
+ addProposalsControls,
15
+ addMeetingsControls,
16
+ addSearchControls,
17
+ addCategoriesControls,
18
+ addHashtagsControls,
19
+ fetchProposals,
20
+ fetchMeetings,
21
+ options,
22
+ show,
23
+ components,
24
+ amendments,
25
+ allMarkers,
26
+ drawMarker,
27
+ getCategory
28
+ } = exports.AwesomeMap;
29
+
30
+ exports.AwesomeMap.allMarkersLoaded = $.noop;
31
+
32
+ const autoResizeMap = (map) => {
33
+ // Setup center/zoom options if specified, otherwise fitbounds
34
+ if(options.center) {
35
+ map.setView(options.center, options.zoom);
36
+ } else {
37
+ map.fitBounds(cluster.getBounds(), { padding: [50, 50] });
77
38
  }
78
-
79
- return marker;
80
39
  };
81
40
 
82
41
  const loadElements = (map) => {
@@ -85,131 +44,168 @@
85
44
  cluster.addTo(map);
86
45
 
87
46
  // Load markers
88
- components.forEach((component) => {
47
+ components.forEach((component) => {
89
48
  if(component.type == "proposals") {
90
- // add control layer for proposals
91
- layers.proposals = {
92
- label: `<span id="awesome_map-component-${component.id}" title="0">${component.name || window.DecidimAwesome.texts.proposals}</span>`,
93
- group: L.featureGroup.subGroup(cluster)
94
- };
95
- control.addOverlay(layers.proposals.group, layers.proposals.label);
96
- layers.proposals.group.addTo(map);
97
-
98
- // add control layer for amendments if any
99
- if(component.amendments) {
100
- layers.amendments = {
101
- label: `<span id="awesome_map-component-${component.d}" title="0">${window.DecidimAwesome.texts.amendments}</span>`,
102
- group: L.featureGroup.subGroup(cluster)
103
- }
104
- control.addOverlay(layers.amendments.group, layers.amendments.label);
105
- layers.amendments.group.addTo(map);
106
- }
49
+ addProposalsControls(map, component);
107
50
 
108
51
  fetchProposals(component, '', (element, marker) => {
109
- console.log(element.state, show[element.state || 'notAnswered'], show, element);
52
+ // console.log(element.state, show[element.state || 'notAnswered'], show, element);
110
53
  if(show[element.state || 'notAnswered']) {
111
- drawMarker(element, marker, component).addTo(layers.proposals.group)
54
+ drawMarker(element, marker, component).addTo(layers.proposals.group);
55
+ // Add hashtags menu items here, only hashtags with proposals associated will be present
56
+ if(options.menu.hashtags) {
57
+ addHashtagsControls(map, element.hashtags, marker);
58
+ }
112
59
  }
113
- }, () => {
114
- // finall call
115
- map.fitBounds(cluster.getBounds(), { padding: [50, 50] });
60
+ }, () => { // final call
61
+ // Setup center/zoom options if specified, otherwise fitbounds
62
+ autoResizeMap(map);
63
+
116
64
  allMarkers.forEach((item) => {
117
65
  // add marker to amendments layers if it's an amendment
118
66
  if(amendments.find((a) => a == item.element.id)) {
119
67
  item.marker.removeFrom(layers.proposals.group);
120
- item.marker.addTo(layers.amendments.group);
68
+ if(options.menu.amendments) {
69
+ item.marker.addTo(layers.amendments.group);
70
+ }
121
71
  }
122
72
  });
73
+ // Call a trigger, might be useful for customizations
74
+ exports.AwesomeMap.allMarkersLoaded();
123
75
  });
124
- }
125
-
126
- if(component.type == "meetings") {
127
- // add control layer for meetings
128
- layers.meetings = {
129
- label: `<span id="awesome_map-component-${component.id}" title="0">${component.name || window.DecidimAwesome.texts.meetings}</span>`,
130
- group: L.featureGroup.subGroup(cluster)
131
- };
132
- control.addOverlay(layers.meetings.group, layers.meetings.label);
133
- layers.meetings.group.addTo(map);
134
-
135
- fetchMeetings(component, '', (element, marker) => {
76
+ }
77
+
78
+ if(options.menu.meetings && component.type == "meetings") {
79
+ addMeetingsControls(map, component);
80
+
81
+ fetchMeetings(component, '', (element, marker) => {
136
82
  drawMarker(element, marker, component).addTo(layers.meetings.group);
137
- }, () => {
138
- map.fitBounds(cluster.getBounds(), { padding: [50, 50] });
83
+ }, () => autoResizeMap(map) );
84
+ }
85
+ });
86
+
87
+ /*
88
+ * We add all categories and hide those that have no proposals
89
+ * This is done this way to ensure all parent categories are displayed
90
+ * even if the have not proposals associated
91
+ */
92
+ addSearchControls(map);
93
+ addCategoriesControls(map);
94
+
95
+ // category events
96
+ $("#awesome-map").on("change", ".awesome_map-categories-selector", (e) => {
97
+ e.preventDefault();
98
+ e.stopPropagation();
99
+ const id = $(e.target).closest("label").data("layer");
100
+ const cat = getCategory(id);
101
+ // console.log("changed, layer", id, "cat", cat, "checked", e.target.checked, e);
102
+ if(cat) {
103
+ const layer = layers[cat.id];
104
+ if(e.target.checked) {
105
+ // show group of markers
106
+ map.addLayer(layer.group);
107
+
108
+ // if it's a children, put the parent to indeterminate
109
+ indeterminateInput(cat.parent);
110
+ } else {
111
+ // hide group of markers
112
+ map.removeLayer(layer.group);
113
+ // if it's a children, put the parent to indeterminate
114
+ cat.children().forEach((c) => {
115
+ let $el = $(`.awesome_map-category-${c.id}`);
116
+ if($el.parent().prev().prop("checked")) {
117
+ $el.click();
118
+ }
139
119
  });
120
+ }
121
+ // sync tags
122
+ updateHashtagLayers();
140
123
  }
141
124
  });
142
125
 
143
-
144
- // add categories control layers
145
- if(window.AwesomeMap.categories.length) {
146
- let lastLayer = layers[Object.keys(layers)[Object.keys(layers).length - 1]];
147
- // Add Categories "title"
148
- if(lastLayer) {
149
- lastLayer.label = `${lastLayer.label}<hr><b>${window.DecidimAwesome.texts.categories}</b>`;
150
- control.removeLayer(lastLayer.group);
151
- control.addOverlay(lastLayer.group, lastLayer.label);
126
+ const indeterminateInput = (id) => {
127
+ $('[class^="awesome_map-category-"]').parent().prev().prop("indeterminate", false);
128
+ if(id) {
129
+ let $input = $(`.awesome_map-category-${id}`).parent().prev();
130
+ if(!$input.prop("checked")) {
131
+ $input.prop("indeterminate", true);
132
+ }
152
133
  }
153
-
154
- window.AwesomeMap.categories.forEach((category) => {
155
- // add control layer for this category
156
- layers[category.id] = {
157
- label: `<i class="awesome_map-category_${category.id}"></i> ${category.name}`,
158
- group: L.featureGroup.subGroup(cluster)
159
- };
160
- layers[category.id].group.addTo(map);
161
- control.addOverlay(layers[category.id].group, layers[category.id].label);
162
- // hide layer by default, it will be activated if there's any marker in it
163
- setTimeout(() => {
164
- $(`.awesome_map-category_${category.id}`).closest("label").hide();
165
- });
134
+ };
135
+
136
+ const updateHashtagLayers = () => {
137
+ // hide all
138
+ $(".awesome_map-hashtags-selector").each((_idx, el) => {
139
+ const layer = layers[$(el).closest("label").data("layer")];
140
+ if(layer) {
141
+ map.removeLayer(layer.group);
142
+ }
166
143
  });
167
-
168
- // watch events for subcategories syncronitzation
169
- const getCatFromClass = (name) => {
170
- let id = name.match(/awesome_map-category_(\d+)/)
171
- if(!id) return;
172
- const cat = getCategory(id[1]);
173
- if(!cat || !cat.name) return;
174
-
175
- return cat;
176
- };
177
-
178
- const indeterminateInput = (id) => {
179
- $('[class^="awesome_map-category_"]').parent().prev().prop("indeterminate", false);
180
- if(id) {
181
- let $input = $(`.awesome_map-category_${id}`).parent().prev();
182
- if(!$input.prop("checked")) {
183
- $input.prop("indeterminate", true);
184
- }
144
+ // show selected only
145
+ $(".awesome_map-hashtags-selector:checked").each((_idx, el) => {
146
+ const layer = layers[$(el).closest("label").data("layer")];
147
+ if(layer) {
148
+ map.addLayer(layer.group);
185
149
  }
186
- };
187
-
188
- map.on('overlayadd', (e) => {
189
- const cat = getCatFromClass(e.name);
190
- if(!cat) return;
191
- // if it's a children, put the parent to indeterminate
192
- indeterminateInput(cat.parent);
193
150
  });
194
-
195
- // on remove a parent category, remove all children
196
- map.on('overlayremove', (e) => {
197
- const cat = getCatFromClass(e.name);
198
- if(!cat) return;
199
- cat.children().forEach((c) => {
200
- let $el = $(`.awesome_map-category_${c.id}`);
201
- if($el.parent().prev().prop("checked")) {
202
- $el.click();
203
- }
204
- });
151
+ // hide non-selected categories
152
+ $(".awesome_map-categories-selector:not(:checked)").each((_idx, el) => {
153
+ const layer = layers[$(el).closest("label").data("layer")];
154
+ console.log(el, layer, map)
155
+ if(layer) {
156
+ map.addLayer(layer.group);
157
+ map.removeLayer(layer.group);
158
+ }
205
159
  });
160
+ };
161
+
162
+ // hashtag events
163
+ $("#awesome-map").on("change", ".awesome_map-hashtags-selector", (e) => {
164
+ e.preventDefault();
165
+ e.stopPropagation();
166
+ const tag = $(e.target).closest("label").data("layer");
167
+ // console.log("changed, layer", tag, "checked", e.target.checked, e);
168
+ if(tag) {
169
+ updateHashtagLayers();
170
+ }
171
+ });
206
172
 
207
- }
173
+ // select/deselect all tags
174
+ $("#awesome-map").on("click", ".awesome_map-toggle_all_tags", (e) => {
175
+ e.preventDefault();
176
+ e.stopPropagation();
177
+ $("#awesome-map .awesome_map-hashtags-selector").prop("checked", $("#awesome-map .awesome_map-hashtags-selector:checked").length < $("#awesome-map .awesome_map-hashtags-selector").length);
178
+ updateHashtagLayers();
179
+ });
208
180
 
181
+ // sub-layer hashtag title toggle
182
+ $("#awesome-map").on("click", ".awesome_map-title-control", (e) => {
183
+ e.preventDefault();
184
+ e.stopPropagation();
185
+ $("#awesome_map-hashtags-control").toggleClass("active");
186
+ });
209
187
  };
210
188
 
211
- $("#map").on("ready.decidim", (ev, map) => {
189
+
190
+ $("#map").on("ready.decidim", (_e, map) => {
191
+ if(options.center) {
192
+ map.setView(options.center, options.zoom);
193
+ }
212
194
  loadElements(map);
195
+
196
+ // order hashtags alphabetically
197
+ exports.AwesomeMap.hashtagAdded = (_hashtag, $div) => {
198
+ let $last = $div.contents("label:last");
199
+ if($last.prev("label").length) {
200
+ // move the label to order it alphabetically
201
+ $div.contents("label").each((_idx, el) => {
202
+ if($(el).text().localeCompare($last.text()) > 0) {
203
+ $(el).before($last);
204
+ return false;
205
+ }
206
+ });
207
+ }
208
+ };
213
209
  });
214
210
 
215
211
  })(window);