decidim-accountability 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +46 -0
  3. data/Rakefile +3 -0
  4. data/app/assets/config/decidim_accountability_admin_manifest.js +1 -0
  5. data/app/assets/config/decidim_accountability_manifest.js +1 -0
  6. data/app/assets/images/decidim/accountability/icon.svg +1 -0
  7. data/app/assets/javascripts/decidim/accountability/accountability.js.es6 +10 -0
  8. data/app/assets/javascripts/decidim/accountability/admin/accountability_admin.js +8 -0
  9. data/app/assets/stylesheets/decidim/accountability/_accountability.scss +1 -0
  10. data/app/assets/stylesheets/decidim/accountability/accountability/_cards.scss +13 -0
  11. data/app/assets/stylesheets/decidim/accountability/accountability/_categories.scss +109 -0
  12. data/app/assets/stylesheets/decidim/accountability/accountability/_lines_breadcrumb.scss +29 -0
  13. data/app/assets/stylesheets/decidim/accountability/accountability/_results.scss +144 -0
  14. data/app/commands/decidim/accountability/admin/create_result.rb +72 -0
  15. data/app/commands/decidim/accountability/admin/create_status.rb +42 -0
  16. data/app/commands/decidim/accountability/admin/create_timeline_entry.rb +40 -0
  17. data/app/commands/decidim/accountability/admin/update_result.rb +80 -0
  18. data/app/commands/decidim/accountability/admin/update_status.rb +46 -0
  19. data/app/commands/decidim/accountability/admin/update_template_texts.rb +47 -0
  20. data/app/commands/decidim/accountability/admin/update_timeline_entry.rb +44 -0
  21. data/app/controllers/decidim/accountability/admin/application_controller.rb +15 -0
  22. data/app/controllers/decidim/accountability/admin/imports_controller.rb +30 -0
  23. data/app/controllers/decidim/accountability/admin/results_controller.rb +84 -0
  24. data/app/controllers/decidim/accountability/admin/statuses_controller.rb +70 -0
  25. data/app/controllers/decidim/accountability/admin/template_texts_controller.rb +38 -0
  26. data/app/controllers/decidim/accountability/admin/timeline_entries_controller.rb +75 -0
  27. data/app/controllers/decidim/accountability/application_controller.rb +13 -0
  28. data/app/controllers/decidim/accountability/result_widgets_controller.rb +19 -0
  29. data/app/controllers/decidim/accountability/results_controller.rb +77 -0
  30. data/app/forms/decidim/accountability/admin/result_form.rb +74 -0
  31. data/app/forms/decidim/accountability/admin/status_form.rb +21 -0
  32. data/app/forms/decidim/accountability/admin/template_texts_form.rb +19 -0
  33. data/app/forms/decidim/accountability/admin/timeline_entry_form.rb +20 -0
  34. data/app/helpers/decidim/accountability/application_helper.rb +50 -0
  35. data/app/models/decidim/accountability/application_record.rb +10 -0
  36. data/app/models/decidim/accountability/result.rb +66 -0
  37. data/app/models/decidim/accountability/status.rb +18 -0
  38. data/app/models/decidim/accountability/template_texts.rb +17 -0
  39. data/app/models/decidim/accountability/timeline_entry.rb +11 -0
  40. data/app/services/decidim/accountability/csv_exporter.rb +77 -0
  41. data/app/services/decidim/accountability/csv_importer.rb +106 -0
  42. data/app/services/decidim/accountability/result_search.rb +40 -0
  43. data/app/services/decidim/accountability/result_stats_calculator.rb +52 -0
  44. data/app/services/decidim/accountability/results_calculator.rb +34 -0
  45. data/app/views/decidim/accountability/admin/imports/new.html.erb +47 -0
  46. data/app/views/decidim/accountability/admin/results/_form.html.erb +70 -0
  47. data/app/views/decidim/accountability/admin/results/edit.html.erb +9 -0
  48. data/app/views/decidim/accountability/admin/results/index.html.erb +52 -0
  49. data/app/views/decidim/accountability/admin/results/new.html.erb +9 -0
  50. data/app/views/decidim/accountability/admin/shared/_subnav.html.erb +3 -0
  51. data/app/views/decidim/accountability/admin/statuses/_form.html.erb +23 -0
  52. data/app/views/decidim/accountability/admin/statuses/edit.html.erb +8 -0
  53. data/app/views/decidim/accountability/admin/statuses/index.html.erb +45 -0
  54. data/app/views/decidim/accountability/admin/statuses/new.html.erb +8 -0
  55. data/app/views/decidim/accountability/admin/template_texts/_form.html.erb +30 -0
  56. data/app/views/decidim/accountability/admin/template_texts/edit.html.erb +8 -0
  57. data/app/views/decidim/accountability/admin/timeline_entries/_form.html.erb +15 -0
  58. data/app/views/decidim/accountability/admin/timeline_entries/edit.html.erb +8 -0
  59. data/app/views/decidim/accountability/admin/timeline_entries/index.html.erb +41 -0
  60. data/app/views/decidim/accountability/admin/timeline_entries/new.html.erb +8 -0
  61. data/app/views/decidim/accountability/result_widgets/show.html.erb +2 -0
  62. data/app/views/decidim/accountability/results/_home_categories.html.erb +73 -0
  63. data/app/views/decidim/accountability/results/_home_header.html.erb +24 -0
  64. data/app/views/decidim/accountability/results/_linked_results.html.erb +12 -0
  65. data/app/views/decidim/accountability/results/_nav_breadcrumb.html.erb +29 -0
  66. data/app/views/decidim/accountability/results/_results_leaf.html.erb +45 -0
  67. data/app/views/decidim/accountability/results/_results_parent.html.erb +32 -0
  68. data/app/views/decidim/accountability/results/_scope_filters.html.erb +14 -0
  69. data/app/views/decidim/accountability/results/_search.html.erb +12 -0
  70. data/app/views/decidim/accountability/results/_show_leaf.html.erb +79 -0
  71. data/app/views/decidim/accountability/results/_show_parent.html.erb +25 -0
  72. data/app/views/decidim/accountability/results/_stats.html.erb +11 -0
  73. data/app/views/decidim/accountability/results/_stats_box.html.erb +36 -0
  74. data/app/views/decidim/accountability/results/_tags.html.erb +10 -0
  75. data/app/views/decidim/accountability/results/_timeline.html.erb +24 -0
  76. data/app/views/decidim/accountability/results/home.html.erb +9 -0
  77. data/app/views/decidim/accountability/results/index.html.erb +19 -0
  78. data/app/views/decidim/accountability/results/index.js.erb +2 -0
  79. data/app/views/decidim/accountability/results/show.html.erb +14 -0
  80. data/config/i18n-tasks.yml +10 -0
  81. data/config/locales/ca.yml +190 -0
  82. data/config/locales/en.yml +190 -0
  83. data/config/locales/es.yml +190 -0
  84. data/config/locales/eu.yml +79 -0
  85. data/config/locales/fi.yml +77 -0
  86. data/db/migrate/20170425154712_create_accountability_statuses.rb +13 -0
  87. data/db/migrate/20170426104125_create_accountability_results.rb +22 -0
  88. data/db/migrate/20170508104902_add_description_and_progress_to_statuses.rb +6 -0
  89. data/db/migrate/20170508161109_create_template_texts.rb +14 -0
  90. data/db/migrate/20170606102902_add_index_to_accountability_results_on_external_id.rb +5 -0
  91. data/db/migrate/20170620154712_create_accountability_timeline_entries.rb +13 -0
  92. data/db/migrate/20170623094200_migrate_accountability_results_category.rb +13 -0
  93. data/db/migrate/20170623144902_add_children_counter_cache_to_results.rb +5 -0
  94. data/lib/decidim/accountability.rb +12 -0
  95. data/lib/decidim/accountability/admin.rb +10 -0
  96. data/lib/decidim/accountability/admin_engine.rb +32 -0
  97. data/lib/decidim/accountability/feature.rb +86 -0
  98. data/lib/decidim/accountability/list_engine.rb +27 -0
  99. data/lib/decidim/accountability/test/factories.rb +45 -0
  100. metadata +238 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f9d0db9ff68db88ec5363e6fb2128c2940487bbe
4
+ data.tar.gz: ce9a332bd2dcde8d1a48ed9b3b3872b67a0202a4
5
+ SHA512:
6
+ metadata.gz: ab4242241dc48f9af57673929a27e1e31ee2a50583de19cfed1128f5b2f8baf4fe4e8638edd2acd1e69b32416e8c0aa1c5af1f7ac47f92fb445926a17633c8db
7
+ data.tar.gz: 7d81f544cd7050f662fa60bceaca743e90f9604120d78604ec4f16eb7973b46c9b7ed55c61efa49f164a1d963cc5c536c952b719f95b37e513c8cfc75490195b
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # Decidim::Accountability
2
+
3
+ [![Build Status](https://www.travis-ci.org/decidim/decidim-accountability.svg?branch=master)](https://www.travis-ci.org/decidim/decidim-accountability)
4
+
5
+
6
+ The Accountability module adds results to any participatory process. It adds a CRUD engine to the admin and public views scoped inside the participatory process. Accountability will link to related meetings and proposals and will be used to show the progress on the related proposals.
7
+
8
+ It also has a CSV importer for results, you can read [here](doc/csv_importer.md) about how it works, the CSV columns and what they mean.
9
+
10
+ ## Usage
11
+ Accountability will be available as a Feature for a Participatory Process.
12
+
13
+ ## Installation
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'decidim-accountability'
18
+ ```
19
+
20
+ And then execute:
21
+ ```bash
22
+ $ bundle
23
+ ```
24
+
25
+ ## Migration from `Decidim::Results` module
26
+ To migrate results from Decidim::Results to Decidim::Accountability you can use a rake task like [this one in decidim-barcelona](https://github.com/PopulateTools/decidim-barcelona/blob/accountability/lib/tasks/migrate_results_to_accountability.rake). The task asumes that the accountability feature for the process has already been created. It takes a process ID as an argument, and defaults to 1 if none is provided:
27
+ ```bash
28
+ $ bundle exec rake migrate:results_to_accountability[PROCESS_ID]
29
+ ```
30
+
31
+
32
+ ## Local development setup
33
+ Clone [decidim-barcelona](https://github.com/PopulateTools/decidim-barcelona), at the same directory level as this `decidim-accountability` clone, and then checkout the `accountability-localdev` branch.
34
+
35
+ Inside the `decidim-barcelona` directory run:
36
+
37
+ - `bundle exec rake db:setup`
38
+ - `bundle exec rake test_data:load`
39
+
40
+ Now you should be able to start a local server with `bundle exec rails s`.
41
+
42
+ ## Contributing
43
+ See [Decidim](https://github.com/AjuntamentdeBarcelona/decidim).
44
+
45
+ ## License
46
+ See [Decidim](https://github.com/AjuntamentdeBarcelona/decidim).
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/dev/common_rake"
@@ -0,0 +1 @@
1
+ //= link decidim/accountability/admin/accountability_admin.js
@@ -0,0 +1 @@
1
+ //= link decidim/accountability/accountability.js
@@ -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.94zM16 22.48a1 1 0 0 1-.68-.28l-4.08-4a1 1 0 0 1 1.36-1.39l3.4 3.3 8-8.8a1 1 0 0 1 1.44 1.31l-8.69 9.55a1 1 0 0 1-.69.32z"/></svg>
@@ -0,0 +1,10 @@
1
+ // = require_self
2
+
3
+ $(() => {
4
+ /* Show category list on click when we are on a small scren */
5
+ if ($(window).width() < 768) {
6
+ $('.category--section').click((e) => {
7
+ $(e.currentTarget).next('.category--elements').toggleClass('active');
8
+ });
9
+ }
10
+ })
@@ -0,0 +1,8 @@
1
+ // = require_self
2
+
3
+ $("#result_decidim_accountability_status_id").change(function () {
4
+ progress = $(this).find(':selected').data('progress')
5
+ if (progress || progress == 0) {
6
+ $("#result_progress").val(progress);
7
+ }
8
+ });
@@ -0,0 +1 @@
1
+ @import "accountability/*";
@@ -0,0 +1,13 @@
1
+ .accountability {
2
+ .card__link--block {
3
+ display: block;
4
+ }
5
+ .card--list__data {
6
+ min-width: 7rem;
7
+ }
8
+ .card--meta {
9
+ span {
10
+ margin-right: 0.5rem;
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,109 @@
1
+ .accountability {
2
+ .categories {
3
+ .categories--header {
4
+ border-bottom: 1px solid $medium-gray;
5
+ padding-bottom: 1rem;
6
+ margin-bottom: 1rem;
7
+
8
+ .icon--arrow-bottom {
9
+ fill: lighten($dark-gray, 50);
10
+ }
11
+
12
+ span {
13
+ text-transform: uppercase;
14
+ font-size: 1.15rem;
15
+ color: lighten($dark-gray, 50);
16
+ }
17
+ }
18
+
19
+ .categories--group {
20
+ margin-bottom: 2rem;
21
+
22
+ @include breakpoint(medium) {
23
+ display: flex;
24
+ margin-bottom: 4rem;
25
+ }
26
+
27
+ .category--title {
28
+ background: $white;
29
+ padding: 1.5rem 2rem;
30
+ min-height: 9rem;
31
+
32
+ @include breakpoint(medium) {
33
+ height: calc(100% - 1.875rem);
34
+ }
35
+
36
+ p {
37
+ font-weight: 600;
38
+ margin-bottom: 0.75rem;
39
+ }
40
+
41
+ .progress {
42
+ margin-bottom: 0.5rem;
43
+ }
44
+ .progress-info {
45
+ position: relative;
46
+ margin-bottom: 1.5rem;
47
+
48
+ .progress-figure {
49
+ display: inline-block;
50
+ }
51
+ .category--count {
52
+ position: absolute;
53
+ right: 0;
54
+ top: 0.5rem;
55
+ color: lighten($dark-gray, 50);
56
+ }
57
+ }
58
+ }
59
+
60
+ .card__link {
61
+ .category--line {
62
+ background: $light-gray-dark;
63
+ border-radius: 4px;
64
+ min-height: 9rem;
65
+ padding: 1rem;
66
+ margin-bottom: 1.875rem;
67
+ position: relative;
68
+
69
+ strong {
70
+ font-weight: 600;
71
+ color: $secondary;
72
+ }
73
+
74
+ .progress-figure {
75
+ position: absolute;
76
+ bottom: 1rem;
77
+ }
78
+ .category--count {
79
+ color: lighten($dark-gray, 50);
80
+ position: absolute;
81
+ right: 1rem;
82
+ bottom: 1rem;
83
+ font-size: 80%;
84
+ }
85
+ }
86
+ &:hover {
87
+ .category--count {
88
+ color: lighten($dark-gray, 50);
89
+ }
90
+ strong {
91
+ color: scale-color($anchor-color, $lightness: -14%);
92
+ }
93
+ }
94
+ }
95
+ }
96
+
97
+ .category--elements.active {
98
+ display: block !important;
99
+
100
+ .medium-4:first-child {
101
+ margin-top: 1rem;
102
+ }
103
+ }
104
+
105
+ .progress-figure {
106
+ color: lighten($dark-gray, 50);
107
+ }
108
+ }
109
+ }
@@ -0,0 +1,29 @@
1
+ .lines-breadcrumb {
2
+ margin-bottom: 2rem;
3
+
4
+ .breadcrumb--separator {
5
+ color: darken($light-gray, 40);
6
+ padding: 0 0.25rem;
7
+ }
8
+
9
+ div {
10
+ display: inline-block;
11
+ }
12
+
13
+ a {
14
+ font-weight: 600;
15
+ color: $dark-gray;
16
+ }
17
+
18
+ ul {
19
+ list-style: none;
20
+ margin-left: 0;
21
+ }
22
+
23
+ .percentage {
24
+ color: darken($light-gray, 40);
25
+ font-weight: 400;
26
+ padding-left: 0.15rem;
27
+ display: inline-block;
28
+ }
29
+ }
@@ -0,0 +1,144 @@
1
+ .accountability {
2
+ .intro {
3
+ ul {
4
+ margin-bottom: 1rem;
5
+ }
6
+ .progress-level {
7
+ background: $white;
8
+ padding: 1.5rem 1.75rem;
9
+
10
+ p {
11
+ font-weight: 600;
12
+ text-transform: uppercase;
13
+ margin-bottom: 0.25rem;
14
+ display: inline-block;
15
+ margin-right: 0.5rem;
16
+ font-size: 1.25rem;
17
+ }
18
+
19
+ .icon {
20
+ background: lighten($dark-gray, 50);
21
+ border-radius: 50%;
22
+ fill: white;
23
+ padding: 0.15rem;
24
+ }
25
+
26
+ .progress {
27
+ max-width: 85%;
28
+ margin-bottom: 0;
29
+ }
30
+
31
+ .progress-figure {
32
+ font-size: 2.5rem;
33
+ font-weight: 300;
34
+ color: lighten($dark-gray, 50);
35
+
36
+ @include breakpoint(medium) {
37
+ font-size: 4rem;
38
+ }
39
+ }
40
+ }
41
+ }
42
+
43
+ .scope-filters {
44
+ div {
45
+ color: lighten($dark-gray, 50);
46
+ text-transform: uppercase;
47
+ margin-bottom: 0.15rem;
48
+ }
49
+ span {
50
+ margin-right: 0.5rem;
51
+ }
52
+ ul {
53
+ display: inline;
54
+ }
55
+ li.active {
56
+ background-color: $medium-gray;
57
+ }
58
+ }
59
+
60
+ .description {
61
+ margin-bottom: 1rem;
62
+ }
63
+ .title-action {
64
+ margin-bottom: 0.5rem;
65
+ }
66
+ }
67
+
68
+ .result-view {
69
+ .title {
70
+ display: flex;
71
+ align-items: flex-start;
72
+ margin-bottom: 1rem;
73
+ flex-direction: column;
74
+
75
+ .icon {
76
+ fill: $secondary;
77
+ min-width: 1.5rem;
78
+ min-height: 1.5rem;
79
+ margin-bottom: 0.5rem;
80
+
81
+ @include breakpoint(medium) {
82
+ margin-right: 0.75rem;
83
+ margin-top: 0.5rem;
84
+ }
85
+ }
86
+
87
+ @include breakpoint(medium) {
88
+ flex-direction: row;
89
+ }
90
+ }
91
+
92
+ .progress-level {
93
+ background: $white;
94
+ border-radius: 4px;
95
+ padding: 1.5rem;
96
+ border: 1px solid $medium-gray;
97
+
98
+ .progress-label {
99
+ display: flex;
100
+ justify-content: space-between;
101
+ align-items: flex-end;
102
+ margin-bottom: 0.5rem;
103
+
104
+ .progress-text {
105
+ text-transform: uppercase;
106
+ color: lighten($dark-gray, 30);
107
+ }
108
+ .progress-figure {
109
+ line-height: 1;
110
+ font-size: 2.25rem;
111
+ font-weight: 600;
112
+ }
113
+ }
114
+ }
115
+
116
+ .result-description div {
117
+ margin-bottom: 1rem;
118
+ }
119
+
120
+ .result-meta {
121
+ margin-bottom: 0.5rem;
122
+ font-size: 1.25rem;
123
+
124
+ .result-meta--label {
125
+ font-weight: 600;
126
+ color: lighten($dark-gray, 30);
127
+ }
128
+ .result-meta--data {
129
+ font-size: 1.15rem;
130
+ }
131
+ }
132
+
133
+ hr {
134
+ width: 100%;
135
+ margin: 0 0 3rem 0;
136
+ }
137
+
138
+ .timeline {
139
+ .timeline__info {
140
+ background-color: transparent;
141
+ border: none;
142
+ }
143
+ }
144
+ }
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Accountability
5
+ module Admin
6
+ # This command is executed when the user creates a Result from the admin
7
+ # panel.
8
+ class CreateResult < Rectify::Command
9
+ def initialize(form)
10
+ @form = form
11
+ end
12
+
13
+ # Creates the result if valid.
14
+ #
15
+ # Broadcasts :ok if successful, :invalid otherwise.
16
+ def call
17
+ return broadcast(:invalid) if @form.invalid?
18
+
19
+ transaction do
20
+ create_result
21
+ link_meetings
22
+ link_proposals
23
+ end
24
+
25
+ broadcast(:ok)
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :result
31
+
32
+ def create_result
33
+ @result = Result.create!(
34
+ feature: @form.current_feature,
35
+ scope: @form.scope,
36
+ category: @form.category,
37
+ parent_id: @form.parent_id,
38
+ title: @form.title,
39
+ description: @form.description,
40
+ external_id: @form.external_id,
41
+ start_date: @form.start_date,
42
+ end_date: @form.end_date,
43
+ progress: @form.progress,
44
+ decidim_accountability_status_id: @form.decidim_accountability_status_id
45
+ )
46
+ end
47
+
48
+ def proposals
49
+ @proposals ||= result.sibling_scope(:proposals).where(id: @form.proposal_ids)
50
+ end
51
+
52
+ def meeting_ids
53
+ @meeting_ids ||= proposals.flat_map do |proposal|
54
+ proposal.linked_resources(:meetings, "proposals_from_meeting").pluck(:id)
55
+ end.uniq
56
+ end
57
+
58
+ def meetings
59
+ @meetings ||= result.sibling_scope(:meetings).where(id: meeting_ids)
60
+ end
61
+
62
+ def link_proposals
63
+ result.link_resources(proposals, "included_proposals")
64
+ end
65
+
66
+ def link_meetings
67
+ result.link_resources(meetings, "meetings_through_proposals")
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end