decidim-comparative_stats 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE-AGPLv3.txt +661 -0
- data/README.md +187 -0
- data/Rakefile +40 -0
- data/app/assets/config/admin/comparative_stats_manifest.css +4 -0
- data/app/assets/config/admin/comparative_stats_manifest.js +2 -0
- data/app/assets/config/comparative_stats_manifest.css +4 -0
- data/app/assets/config/comparative_stats_manifest.js +2 -0
- data/app/assets/images/bcn-logo.png +0 -0
- data/app/assets/images/decidim/comparative_stats/icon.svg +1 -0
- data/app/assets/images/platoniq-logo.png +0 -0
- data/app/assets/javascripts/decidim/comparative_stats/geocoded_events.js.es6 +94 -0
- data/app/assets/javascripts/decidim/comparative_stats/graphs.js.es6 +13 -0
- data/app/assets/stylesheets/decidim/comparative_stats/geocoded_events.scss +23 -0
- data/app/assets/stylesheets/decidim/comparative_stats/graphs.scss +6 -0
- data/app/assets/stylesheets/decidim/comparative_stats/widget.scss +8 -0
- data/app/cells/decidim/comparative_stats/metric_piecharts/show.erb +14 -0
- data/app/cells/decidim/comparative_stats/metric_piecharts_cell.rb +39 -0
- data/app/cells/decidim/comparative_stats/metric_timelines/show.erb +14 -0
- data/app/cells/decidim/comparative_stats/metric_timelines_cell.rb +23 -0
- data/app/cells/decidim/comparative_stats/participatory_processes_timeline/show.erb +55 -0
- data/app/cells/decidim/comparative_stats/participatory_processes_timeline_cell.rb +51 -0
- data/app/cells/decidim/comparative_stats/participatory_spaces_geocoded_events/show.erb +55 -0
- data/app/cells/decidim/comparative_stats/participatory_spaces_geocoded_events_cell.rb +108 -0
- data/app/commands/decidim/comparative_stats/admin/create_endpoint.rb +46 -0
- data/app/commands/decidim/comparative_stats/admin/destroy_endpoint.rb +43 -0
- data/app/commands/decidim/comparative_stats/admin/update_endpoint.rb +47 -0
- data/app/controllers/decidim/comparative_stats/admin/application_controller.rb +16 -0
- data/app/controllers/decidim/comparative_stats/admin/endpoints_controller.rb +83 -0
- data/app/controllers/decidim/comparative_stats/admin/graphs_controller.rb +16 -0
- data/app/controllers/decidim/comparative_stats/widgets_controller.rb +31 -0
- data/app/forms/decidim/comparative_stats/admin/endpoint_form.rb +26 -0
- data/app/helpers/decidim/comparative_stats/application_helper.rb +27 -0
- data/app/models/decidim/comparative_stats/application_record.rb +10 -0
- data/app/models/decidim/comparative_stats/endpoint.rb +22 -0
- data/app/permissions/decidim/comparative_stats/admin/permissions.rb +24 -0
- data/app/presenters/decidim/comparative_stats/admin_log/endpoint_presenter.rb +46 -0
- data/app/views/decidim/comparative_stats/admin/endpoints/_form.html.erb +7 -0
- data/app/views/decidim/comparative_stats/admin/endpoints/edit.html.erb +16 -0
- data/app/views/decidim/comparative_stats/admin/endpoints/index.html.erb +66 -0
- data/app/views/decidim/comparative_stats/admin/endpoints/new.html.erb +16 -0
- data/app/views/decidim/comparative_stats/admin/graphs/show.html.erb +15 -0
- data/app/views/decidim/comparative_stats/widgets/_all.html.erb +1 -0
- data/app/views/decidim/comparative_stats/widgets/_embed.html.erb +7 -0
- data/app/views/decidim/comparative_stats/widgets/_embed_modal.html.erb +27 -0
- data/app/views/decidim/comparative_stats/widgets/_global_stats.html.erb +4 -0
- data/app/views/decidim/comparative_stats/widgets/_global_stats_timeline.html.erb +4 -0
- data/app/views/decidim/comparative_stats/widgets/_processes_timeline.html.erb +4 -0
- data/app/views/decidim/comparative_stats/widgets/_spaces_geocoded_events.html.erb +5 -0
- data/app/views/decidim/comparative_stats/widgets/_tabs.html.erb +19 -0
- data/app/views/decidim/comparative_stats/widgets/show.html.erb +1 -0
- data/app/views/layouts/decidim/admin/comparative_stats.html.erb +28 -0
- data/app/views/layouts/decidim/comparative_stats/widget.html.erb +22 -0
- data/config/i18n-tasks.yml +10 -0
- data/config/locales/ca.yml +57 -0
- data/config/locales/cs.yml +57 -0
- data/config/locales/en.yml +64 -0
- data/config/locales/es.yml +57 -0
- data/db/migrate/20191219104548_create_decidim_comparative_stats_endpoints.rb +13 -0
- data/db/migrate/20200122072955_add_name_version_to_comparative_stats_endpoints.rb +8 -0
- data/db/migrate/20200130203914_rename_version_field_in_comparative_stats_endpoints.rb +7 -0
- data/db/seeds.rb +42 -0
- data/lib/decidim/comparative_stats.rb +22 -0
- data/lib/decidim/comparative_stats/admin.rb +10 -0
- data/lib/decidim/comparative_stats/admin_engine.rb +50 -0
- data/lib/decidim/comparative_stats/api_fetcher.rb +93 -0
- data/lib/decidim/comparative_stats/cached_http_adapter.rb +23 -0
- data/lib/decidim/comparative_stats/engine.rb +34 -0
- data/lib/decidim/comparative_stats/queries/global_events.graphql +84 -0
- data/lib/decidim/comparative_stats/queries/global_history_metrics.graphql +10 -0
- data/lib/decidim/comparative_stats/queries/global_metrics.graphql +6 -0
- data/lib/decidim/comparative_stats/queries/name_and_version.graphql +6 -0
- data/lib/decidim/comparative_stats/queries/participatory_processes.graphql +12 -0
- data/lib/decidim/comparative_stats/queries/v022/global_events.graphql +76 -0
- data/lib/decidim/comparative_stats/test/factories.rb +13 -0
- data/lib/decidim/comparative_stats/version.rb +10 -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/leaflet.js +5 -0
- metadata +234 -0
data/README.md
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
# Decidim::ComparativeStats
|
2
|
+
|
3
|
+
![Test](https://github.com/Platoniq/decidim-module-comparative_stats/workflows/Test/badge.svg)
|
4
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/59d3415b89244ef0d40b/maintainability)](https://codeclimate.com/github/Platoniq/decidim-module-comparative_stats/maintainability)
|
5
|
+
[![Codecov](https://codecov.io/gh/Platoniq/decidim-module-comparative_stats/branch/master/graph/badge.svg?token=XhzWO0IiWt)](https://codecov.io/gh/Platoniq/decidim-module-comparative_stats)
|
6
|
+
|
7
|
+
Allows to compare different Decidim sites by accessing their GraphQL API and
|
8
|
+
generate graphs.
|
9
|
+
|
10
|
+
> NOTE: This module is in beta status, feel free to report issues or contribute in it!
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
This module works by connecting to several Decidim API's.
|
15
|
+
Just go to your `your-decidim-installation.org/admin/comparative_stats` and
|
16
|
+
add endpoints to compare.
|
17
|
+
For instance, Decidim Barcelona endpoint is `https://www.decidim.barcelona/api`
|
18
|
+
|
19
|
+
Then, go to graphs and see some nice graphs!
|
20
|
+
|
21
|
+
Graphs can be embedded anywhere independently, just use the button
|
22
|
+
`embed <>` and copy the code to any other place.
|
23
|
+
|
24
|
+
The generated code will look something like:
|
25
|
+
|
26
|
+
```html
|
27
|
+
<iframe
|
28
|
+
src="http://your_url/comparative_stats/widgets/global_stats.html"
|
29
|
+
frameborder="0"
|
30
|
+
width="100%"
|
31
|
+
height="420"
|
32
|
+
scrolling="vertical"></iframe>
|
33
|
+
```
|
34
|
+
|
35
|
+
You might want to customize the `height` parameter to match your particular case.
|
36
|
+
|
37
|
+
![Barcelona/Helsinki comparison](example.png)
|
38
|
+
*A real example comparing the participatory processes carried out by the cities of Barcelona and Helsinki in 2019*
|
39
|
+
|
40
|
+
## Installation
|
41
|
+
|
42
|
+
Add this line to your application's Gemfile:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
gem "decidim-comparative_stats", "~> 1.0.1"
|
46
|
+
```
|
47
|
+
|
48
|
+
And then execute:
|
49
|
+
|
50
|
+
```bash
|
51
|
+
bundle
|
52
|
+
bundle exec rails decidim_comparative_stats:install:migrations
|
53
|
+
bundle exec rails db:migrate
|
54
|
+
```
|
55
|
+
|
56
|
+
Depending on your Decidim version, choose the corresponding Awesome version to ensure
|
57
|
+
compatibility:
|
58
|
+
|
59
|
+
| Comparative stats version | Compatible Decidim versions |
|
60
|
+
|---|---|
|
61
|
+
| 1.0.x | 0.21.x - 0.23.x |
|
62
|
+
|
63
|
+
## Configuration options
|
64
|
+
|
65
|
+
API queries are cached 1 hour by default.
|
66
|
+
This can be tuned by creating an initializer in your Decidim installation.
|
67
|
+
For instance, create the file `config/initializers/comparative_stats.rb`
|
68
|
+
with this content:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
# frozen_string_literal: true
|
72
|
+
|
73
|
+
Decidim::ComparativeStats.configure do |config|
|
74
|
+
config.stats_cache_expiration_time = 2.hour
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
78
|
+
## Contributing
|
79
|
+
|
80
|
+
See [Decidim](https://github.com/decidim/decidim).
|
81
|
+
|
82
|
+
### Developing
|
83
|
+
|
84
|
+
To start contributing to this project, first:
|
85
|
+
|
86
|
+
- Install the basic dependencies (such as Ruby and PostgreSQL)
|
87
|
+
- Clone this repository
|
88
|
+
|
89
|
+
Decidim's main repository also provides a Docker configuration file if you
|
90
|
+
prefer to use Docker instead of installing the dependencies locally on your
|
91
|
+
machine.
|
92
|
+
|
93
|
+
You can create the development app by running the following commands after
|
94
|
+
cloning this project:
|
95
|
+
|
96
|
+
```bash
|
97
|
+
bundle
|
98
|
+
DATABASE_USERNAME=<username> DATABASE_PASSWORD=<password> bundle exec rake development_app
|
99
|
+
```
|
100
|
+
|
101
|
+
Note that the database user has to have rights to create and drop a database in
|
102
|
+
order to create the dummy test app database.
|
103
|
+
|
104
|
+
Then to test how the module works in Decidim, start the development server:
|
105
|
+
|
106
|
+
```bash
|
107
|
+
cd development_app
|
108
|
+
DATABASE_USERNAME=<username> DATABASE_PASSWORD=<password> bundle exec rails s
|
109
|
+
```
|
110
|
+
|
111
|
+
In case you are using [rbenv](https://github.com/rbenv/rbenv) and have the
|
112
|
+
[rbenv-vars](https://github.com/rbenv/rbenv-vars) plugin installed for it, you
|
113
|
+
can add the environment variables to the root directory of the project in a file
|
114
|
+
named `.rbenv-vars`. If these are defined for the environment, you can omit
|
115
|
+
defining these in the commands shown above.
|
116
|
+
|
117
|
+
#### Code Styling
|
118
|
+
|
119
|
+
Please follow the code styling defined by the different linters that ensure we
|
120
|
+
are all talking with the same language collaborating on the same project. This
|
121
|
+
project is set to follow the same rules that Decidim itself follows.
|
122
|
+
|
123
|
+
[Rubocop](https://rubocop.readthedocs.io/) linter is used for the Ruby language.
|
124
|
+
|
125
|
+
You can run the code styling checks by running the following commands from the
|
126
|
+
console:
|
127
|
+
|
128
|
+
```
|
129
|
+
bundle exec rubocop
|
130
|
+
```
|
131
|
+
|
132
|
+
To ease up following the style guide, you should install the plugin to your
|
133
|
+
favorite editor, such as:
|
134
|
+
|
135
|
+
- Atom - [linter-rubocop](https://atom.io/packages/linter-rubocop)
|
136
|
+
- Sublime Text - [Sublime RuboCop](https://github.com/pderichs/sublime_rubocop)
|
137
|
+
- Visual Studio Code - [Rubocop for Visual Studio Code](https://github.com/misogi/vscode-ruby-rubocop)
|
138
|
+
|
139
|
+
### Testing
|
140
|
+
|
141
|
+
To run the tests run the following in the gem development path:
|
142
|
+
|
143
|
+
```bash
|
144
|
+
bundle
|
145
|
+
DATABASE_USERNAME=<username> DATABASE_PASSWORD=<password> bundle exec rake test_app
|
146
|
+
DATABASE_USERNAME=<username> DATABASE_PASSWORD=<password> bundle exec rspec
|
147
|
+
```
|
148
|
+
|
149
|
+
Note that the database user has to have rights to create and drop a database in
|
150
|
+
order to create the dummy test app database.
|
151
|
+
|
152
|
+
In case you are using [rbenv](https://github.com/rbenv/rbenv) and have the
|
153
|
+
[rbenv-vars](https://github.com/rbenv/rbenv-vars) plugin installed for it, you
|
154
|
+
can add these environment variables to the root directory of the project in a
|
155
|
+
file named `.rbenv-vars`. In this case, you can omit defining these in the
|
156
|
+
commands shown above.
|
157
|
+
|
158
|
+
### Test code coverage
|
159
|
+
|
160
|
+
If you want to generate the code coverage report for the tests, you can use
|
161
|
+
the `SIMPLECOV=1` environment variable in the rspec command as follows:
|
162
|
+
|
163
|
+
```bash
|
164
|
+
SIMPLECOV=1 bundle exec rspec
|
165
|
+
```
|
166
|
+
|
167
|
+
This will generate a folder named `coverage` in the project root which contains
|
168
|
+
the code coverage report.
|
169
|
+
|
170
|
+
### Localization
|
171
|
+
|
172
|
+
If you would like to see this module in your own language, you can help with its
|
173
|
+
translation at Crowdin:
|
174
|
+
|
175
|
+
<https://crowdin.com/translate/decidim-comparative-stats>
|
176
|
+
|
177
|
+
## License
|
178
|
+
|
179
|
+
This engine is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
|
180
|
+
|
181
|
+
## Credits
|
182
|
+
|
183
|
+
This plugin has been developed by ![Platoniq](app/assets/images/platoniq-logo.png)
|
184
|
+
|
185
|
+
> Amb el suport de l'Ajuntament de Barcelona - Direcció de Serveis d'Innovació Democràtica
|
186
|
+
>
|
187
|
+
> ![Logo Barcelona](app/assets/images/bcn-logo.png)
|
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_comparative_stats: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
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35 35"><path d="M17.5 35A17.5 17.5 0 1 1 35 17.5 17.52 17.52 0 0 1 17.5 35zm0-33.06A15.56 15.56 0 1 0 33.06 17.5 15.57 15.57 0 0 0 17.5 1.94zm9.5 13.7H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zm0 3.68H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zM22.26 23H8a1 1 0 0 1 0-1.94h14.26a1 1 0 0 1 0 1.94z"/></svg>
|
Binary file
|
@@ -0,0 +1,94 @@
|
|
1
|
+
// = require leaflet
|
2
|
+
// = require leaflet-svg-icon
|
3
|
+
// = require leaflet.markercluster
|
4
|
+
// = require jquery-tmpl
|
5
|
+
// = require_self
|
6
|
+
|
7
|
+
$(() => {
|
8
|
+
|
9
|
+
var map_object = document.getElementById('geocoded_events');
|
10
|
+
var map = L.map(map_object, {
|
11
|
+
center: [41,2],
|
12
|
+
zoom: 4
|
13
|
+
});
|
14
|
+
|
15
|
+
L.DivIcon.SVGIcon.DecidimIcon = L.DivIcon.SVGIcon.extend({
|
16
|
+
options: {
|
17
|
+
fillColor: "#ef604d",
|
18
|
+
opacity: 0
|
19
|
+
},
|
20
|
+
_createPathDescription: function() {
|
21
|
+
return "M14 1.17a11.685 11.685 0 0 0-11.685 11.685c0 11.25 10.23 20.61 10.665 21a1.5 1.5 0 0 0 2.025 0c0.435-.435 10.665-9.81 10.665-21A11.685 11.685 0 0 0 14 1.17Zm0 17.415A5.085 5.085 0 1 1 19.085 13.5 5.085 5.085 0 0 1 14 18.585Z";
|
22
|
+
},
|
23
|
+
_createCircle: function() {
|
24
|
+
return ""
|
25
|
+
}
|
26
|
+
});
|
27
|
+
|
28
|
+
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
29
|
+
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
30
|
+
}).addTo(map);
|
31
|
+
|
32
|
+
var endpoints = $('#geocoded_events').data('geocoded-events');
|
33
|
+
const popupProposalsTemplateId = "marker-popup-proposal";
|
34
|
+
$.template(popupProposalsTemplateId, $(`#${popupProposalsTemplateId}`).html());
|
35
|
+
const popupMeetingsTemplateId = "marker-popup-meeting";
|
36
|
+
$.template(popupMeetingsTemplateId, $(`#${popupMeetingsTemplateId}`).html());
|
37
|
+
|
38
|
+
const randomColor = () => '#'+Math.floor(Math.random()*16777215).toString(16);
|
39
|
+
|
40
|
+
const getMarker = (id, point, color) => {
|
41
|
+
let coordinates = [point.latitude, point.longitude];
|
42
|
+
let marker = L.marker(coordinates, {
|
43
|
+
icon: new L.DivIcon.SVGIcon.DecidimIcon({fillColor: color})
|
44
|
+
});
|
45
|
+
|
46
|
+
let node = document.createElement("div");
|
47
|
+
|
48
|
+
$.tmpl(id, point).appendTo(node);
|
49
|
+
marker.bindPopup(node, {
|
50
|
+
maxWidth: 640,
|
51
|
+
minWidth: 500,
|
52
|
+
keepInView: true,
|
53
|
+
className: "map-info"
|
54
|
+
}).openPopup();
|
55
|
+
|
56
|
+
return marker;
|
57
|
+
};
|
58
|
+
|
59
|
+
let layers = {};
|
60
|
+
|
61
|
+
for (let endpoint in endpoints) {
|
62
|
+
|
63
|
+
// In the future the color should come from the assigned to the endpoint
|
64
|
+
let color = randomColor();
|
65
|
+
let markerClusters = L.markerClusterGroup({
|
66
|
+
iconCreateFunction: function (cluster) {
|
67
|
+
var childCount = cluster.getChildCount();
|
68
|
+
|
69
|
+
return new L.DivIcon({ html: '<div style="background-color:' + color +'"><span>' + childCount + '</span></div>', className: 'marker-cluster', iconSize: new L.Point(40, 40) });
|
70
|
+
|
71
|
+
}
|
72
|
+
});
|
73
|
+
|
74
|
+
let meetings = endpoints[endpoint].meetings;
|
75
|
+
let proposals = endpoints[endpoint].proposals;
|
76
|
+
|
77
|
+
for(let key in meetings) {
|
78
|
+
markerClusters.addLayer(getMarker(popupMeetingsTemplateId, meetings[key], color));
|
79
|
+
}
|
80
|
+
|
81
|
+
for(let key in proposals) {
|
82
|
+
markerClusters.addLayer(getMarker(popupProposalsTemplateId, proposals[key], color));
|
83
|
+
}
|
84
|
+
markerClusters.addTo(map);
|
85
|
+
let key = '<span class="endpoint-legend"><span class="square" style="background-color:' + color +'"></span>' + endpoints[endpoint].name + '</span>';
|
86
|
+
layers[key] = markerClusters;
|
87
|
+
}
|
88
|
+
|
89
|
+
L.control.layers(null, layers).addTo(map);
|
90
|
+
|
91
|
+
$("[data-tabs]").on('change.zf.tabs', function() {
|
92
|
+
map.invalidateSize(true);
|
93
|
+
});
|
94
|
+
});
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// = require chartkick
|
2
|
+
// = require Chart.bundle
|
3
|
+
// = require_self
|
4
|
+
|
5
|
+
$(() => {
|
6
|
+
//create trigger to resizeEnd event
|
7
|
+
$(window).resize(() => {
|
8
|
+
if(window.resizeTO) clearTimeout(window.resizeTO);
|
9
|
+
window.resizeTO = setTimeout(() => {
|
10
|
+
$(window).trigger('resizeEnd');
|
11
|
+
}, 100);
|
12
|
+
});
|
13
|
+
});
|
@@ -0,0 +1,23 @@
|
|
1
|
+
@import "graphs";
|
2
|
+
@import "decidim/modules/cards";
|
3
|
+
@import "decidim/modules/address";
|
4
|
+
@import "decidim/modules/buttons";
|
5
|
+
@import "decidim/modules/map";
|
6
|
+
@import "decidim/extras/leaflet";
|
7
|
+
|
8
|
+
#geocoded_events{
|
9
|
+
min-height: 360px;
|
10
|
+
height: 100%;
|
11
|
+
|
12
|
+
.endpoint-legend{
|
13
|
+
font-size: .8rem;
|
14
|
+
line-height: .8;
|
15
|
+
|
16
|
+
.square{
|
17
|
+
display: inline-block;
|
18
|
+
width: .9em;
|
19
|
+
height: .9em;
|
20
|
+
margin-right: .3em;
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<div class="row small-up-1 smallmedium-up-2 mediumlarge-up-3 large-up-4 card-grid">
|
2
|
+
<% metrics.each do |name, metric| %>
|
3
|
+
<div class="column" style="padding: 1em">
|
4
|
+
<div class="card">
|
5
|
+
<div class="card-divider">
|
6
|
+
<%= title name %>
|
7
|
+
</div>
|
8
|
+
<div class="card-section">
|
9
|
+
<%= pie_chart metric, id: "pie_chart_#{name}" %>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
14
|
+
</div>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "chartkick"
|
4
|
+
require "chartkick/helper"
|
5
|
+
|
6
|
+
module Decidim
|
7
|
+
module ComparativeStats
|
8
|
+
class MetricPiechartsCell < Decidim::ViewModel
|
9
|
+
include Chartkick::Helper
|
10
|
+
|
11
|
+
def show
|
12
|
+
return unless model
|
13
|
+
|
14
|
+
render :show
|
15
|
+
end
|
16
|
+
|
17
|
+
def endpoints
|
18
|
+
model
|
19
|
+
end
|
20
|
+
|
21
|
+
def title(name)
|
22
|
+
return t "decidim.comparative_stats.metrics.users.title" if name == "users"
|
23
|
+
|
24
|
+
t "decidim.metrics.#{name}.title"
|
25
|
+
end
|
26
|
+
|
27
|
+
def metrics
|
28
|
+
metrics = {}
|
29
|
+
endpoints.each do |endpoint|
|
30
|
+
endpoint.api.fetch_global_metrics.data.metrics.each do |item|
|
31
|
+
metrics[item.name] ||= {}
|
32
|
+
metrics[item.name][endpoint.name] = item.count
|
33
|
+
end
|
34
|
+
end
|
35
|
+
metrics
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|