decidim-accountability 0.10.1 → 0.11.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/assets/javascripts/decidim/accountability/accountability.js.es6 +2 -2
  4. data/app/assets/javascripts/decidim/accountability/admin/accountability_admin.js.es6 +11 -11
  5. data/app/commands/decidim/accountability/admin/create_result.rb +1 -1
  6. data/app/commands/decidim/accountability/admin/create_status.rb +1 -1
  7. data/app/commands/decidim/accountability/admin/destroy_result.rb +43 -0
  8. data/app/controllers/decidim/accountability/admin/application_controller.rb +2 -2
  9. data/app/controllers/decidim/accountability/admin/results_controller.rb +12 -10
  10. data/app/controllers/decidim/accountability/admin/statuses_controller.rb +1 -1
  11. data/app/controllers/decidim/accountability/admin/timeline_entries_controller.rb +1 -1
  12. data/app/controllers/decidim/accountability/application_controller.rb +2 -2
  13. data/app/controllers/decidim/accountability/result_widgets_controller.rb +1 -1
  14. data/app/controllers/decidim/accountability/results_controller.rb +3 -3
  15. data/app/controllers/decidim/accountability/versions_controller.rb +1 -1
  16. data/app/events/decidim/accountability/proposal_linked_event.rb +1 -1
  17. data/app/forms/decidim/accountability/admin/result_form.rb +5 -5
  18. data/app/helpers/decidim/accountability/application_helper.rb +4 -4
  19. data/app/helpers/decidim/accountability/breadcrumb_helper.rb +1 -1
  20. data/app/models/decidim/accountability/result.rb +10 -5
  21. data/app/models/decidim/accountability/status.rb +3 -3
  22. data/app/presenters/decidim/accountability/admin_log/result_presenter.rb +5 -4
  23. data/app/presenters/decidim/accountability/admin_log/value_types/parent_presenter.rb +29 -0
  24. data/app/services/decidim/accountability/result_search.rb +2 -2
  25. data/app/services/decidim/accountability/results_calculator.rb +4 -4
  26. data/app/views/decidim/accountability/admin/results/_form.html.erb +5 -6
  27. data/app/views/decidim/accountability/admin/results/_proposals.html.erb +2 -2
  28. data/app/views/decidim/accountability/admin/results/edit.html.erb +2 -2
  29. data/app/views/decidim/accountability/admin/results/index.html.erb +5 -5
  30. data/app/views/decidim/accountability/admin/results/new.html.erb +2 -2
  31. data/app/views/decidim/accountability/admin/shared/_subnav.html.erb +1 -1
  32. data/app/views/decidim/accountability/admin/statuses/edit.html.erb +2 -3
  33. data/app/views/decidim/accountability/admin/statuses/index.html.erb +3 -3
  34. data/app/views/decidim/accountability/admin/statuses/new.html.erb +2 -3
  35. data/app/views/decidim/accountability/admin/timeline_entries/edit.html.erb +2 -3
  36. data/app/views/decidim/accountability/admin/timeline_entries/index.html.erb +4 -4
  37. data/app/views/decidim/accountability/admin/timeline_entries/new.html.erb +2 -3
  38. data/app/views/decidim/accountability/results/_home_categories.html.erb +3 -3
  39. data/app/views/decidim/accountability/results/_home_header.html.erb +2 -2
  40. data/app/views/decidim/accountability/results/_nav_breadcrumb.html.erb +4 -4
  41. data/app/views/decidim/accountability/results/_results_leaf.html.erb +2 -2
  42. data/app/views/decidim/accountability/results/_results_parent.html.erb +2 -4
  43. data/app/views/decidim/accountability/results/_scope_filters.html.erb +1 -1
  44. data/app/views/decidim/accountability/results/_search.html.erb +2 -2
  45. data/app/views/decidim/accountability/results/_show_leaf.html.erb +2 -2
  46. data/app/views/decidim/accountability/results/_show_parent.html.erb +2 -2
  47. data/app/views/decidim/accountability/results/_stats_box.html.erb +1 -1
  48. data/app/views/decidim/accountability/versions/index.html.erb +1 -1
  49. data/app/views/decidim/participatory_processes/participatory_process_groups/_highlighted_results.html.erb +1 -1
  50. data/app/views/decidim/participatory_processes/participatory_process_groups/_result.html.erb +1 -1
  51. data/app/views/decidim/participatory_spaces/_highlighted_results.html.erb +2 -2
  52. data/app/views/decidim/participatory_spaces/_result.html.erb +1 -1
  53. data/config/locales/ca.yml +12 -8
  54. data/config/locales/en.yml +13 -9
  55. data/config/locales/es.yml +13 -9
  56. data/config/locales/eu.yml +13 -9
  57. data/config/locales/fi.yml +13 -9
  58. data/config/locales/fr.yml +14 -10
  59. data/config/locales/gl.yml +13 -9
  60. data/config/locales/it.yml +13 -9
  61. data/config/locales/nl.yml +22 -18
  62. data/config/locales/pl.yml +13 -9
  63. data/config/locales/pt-BR.yml +13 -9
  64. data/config/locales/pt.yml +13 -9
  65. data/config/locales/ru.yml +0 -1
  66. data/config/locales/sv.yml +13 -9
  67. data/config/locales/uk.yml +0 -1
  68. data/db/migrate/20180305133145_rename_features_to_components_at_accountability.rb +16 -0
  69. data/lib/decidim/accountability.rb +1 -1
  70. data/lib/decidim/accountability/{feature.rb → component.rb} +25 -25
  71. data/lib/decidim/accountability/engine.rb +4 -4
  72. data/lib/decidim/accountability/result_serializer.rb +3 -3
  73. data/lib/decidim/accountability/test/factories.rb +5 -5
  74. data/lib/decidim/accountability/version.rb +1 -1
  75. metadata +26 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 757a3051ec263ec176bc03f9ae7b2ce3a683f3cfe3f862b27366b8696ebe6d6d
4
- data.tar.gz: ace2f7badfb536fd190b30ec68351fc4e90e6ed7da6bbbc72764cdb5f2fa9ec3
3
+ metadata.gz: 5207908e5a433224053e690acac13d24905ab648c799ebedc244dc40ae164d82
4
+ data.tar.gz: dbb8a639b0b117157c9f408914d2dfa222340d6e5f31631ac7f0bde9dc7a76af
5
5
  SHA512:
6
- metadata.gz: fe71357f53a478a380e287d81a52f94ba87100dc2b9be7da74ca19cc940ede34da3ab7448ac994d09f485de38038de214fdf005965a6dbfb3e70009f2cc50781
7
- data.tar.gz: 9858e94c1e805a97382f00551e953ae76cc2ac0c88116910d1ed7a2bf50abd5d0d5beade04286b129075bf55124f85bacd678e81a17deceaabba27b274e78dd6
6
+ metadata.gz: a3b5c13923e8a3c4a4bd35c5c901efef01aa143cf87a678462d19225b5b7af8d71f7510f7e0efb30ea55a96d8940c62f85019cdc611e97288a567969469c2da6
7
+ data.tar.gz: ea3e503988ea03b8d6fa1bbf8c96e6e5f8c48e0cc12a54feadc018053d2331163b65ad351fd9d046d1cea53708b6957290ba8b32137b8120b7b1eb93c8a602c0
data/README.md CHANGED
@@ -4,7 +4,7 @@ The Accountability module adds results to any participatory process. It adds a C
4
4
 
5
5
  ## Usage
6
6
 
7
- Accountability will be available as a Feature for a Participatory Process.
7
+ Accountability will be available as a Component for a Participatory Process.
8
8
 
9
9
  ## Installation
10
10
 
@@ -5,8 +5,8 @@
5
5
  $(() => {
6
6
  // Show category list on click when we are on a small scren
7
7
  if ($(window).width() < 768) {
8
- $('.category--section').click((event) => {
9
- $(event.currentTarget).next('.category--elements').toggleClass('active');
8
+ $(".category--section").click((event) => {
9
+ $(event.currentTarget).next(".category--elements").toggleClass("active");
10
10
  });
11
11
  }
12
12
  })
@@ -2,7 +2,7 @@
2
2
 
3
3
  $("#result_decidim_accountability_status_id").change(function () {
4
4
  /* eslint-disable no-invalid-this */
5
- const progress = $(this).find(':selected').data('progress')
5
+ const progress = $(this).find(":selected").data("progress")
6
6
  if (progress || progress === 0) {
7
7
  $("#result_progress").val(progress);
8
8
  }
@@ -12,7 +12,7 @@ $(function() {
12
12
  $(document).on("open.zf.reveal", "#data_picker-modal", function () {
13
13
  let xhr = null;
14
14
 
15
- $('#data_picker-autocomplete').autoComplete({
15
+ $("#data_picker-autocomplete").autoComplete({
16
16
  minChars: 2,
17
17
  source: function(term, response) {
18
18
  try {
@@ -20,26 +20,26 @@ $(function() {
20
20
  } catch (exception) { xhr = null}
21
21
 
22
22
  xhr = $.getJSON(
23
- 'proposals.json',
23
+ "proposals.json",
24
24
  { term: term },
25
25
  function(data) { response(data); }
26
26
  );
27
27
  },
28
28
  renderItem: function (item, search) {
29
- let sanitizedSearch = search.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
30
- let re = new RegExp(`(${sanitizedSearch.split(' ').join('|')})`, "gi");
29
+ let sanitizedSearch = search.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
30
+ let re = new RegExp(`(${sanitizedSearch.split(" ").join("|")})`, "gi");
31
31
  let title = item[0]
32
32
  let modelId = item[1]
33
33
  let val = `#${modelId}- ${title}`;
34
34
  return `<div class="autocomplete-suggestion" data-model-id="${modelId}" data-val ="${title}">${val.replace(re, "<b>$1</b>")}</div>`;
35
35
  },
36
36
  onSelect: function(event, term, item) {
37
- let choose = $('#proposal-picker-choose')
38
- let modelId = item.data('modelId')
39
- let val = `#${modelId}- ${item.data('val')}`;
40
- choose.data('picker-value', modelId)
41
- choose.data('picker-text', val)
42
- choose.data('picker-choose', '')
37
+ let choose = $("#proposal-picker-choose")
38
+ let modelId = item.data("modelId")
39
+ let val = `#${modelId}- ${item.data("val")}`;
40
+ choose.data("picker-value", modelId)
41
+ choose.data("picker-text", val)
42
+ choose.data("picker-choose", "")
43
43
  }
44
44
  })
45
45
  });
@@ -35,7 +35,7 @@ module Decidim
35
35
  @result = Decidim.traceability.create!(
36
36
  Result,
37
37
  @form.current_user,
38
- feature: @form.current_feature,
38
+ component: @form.current_component,
39
39
  scope: @form.scope,
40
40
  category: @form.category,
41
41
  parent_id: @form.parent_id,
@@ -29,7 +29,7 @@ module Decidim
29
29
 
30
30
  def create_status
31
31
  @status = Status.create!(
32
- feature: @form.current_feature,
32
+ component: @form.current_component,
33
33
  key: @form.key,
34
34
  name: @form.name,
35
35
  description: @form.description,
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Accountability
5
+ module Admin
6
+ # This command is executed when the user destroys a Result from the admin
7
+ # panel.
8
+ class DestroyResult < Rectify::Command
9
+ # Initializes an UpdateResult Command.
10
+ #
11
+ # result - The current instance of the result to be destroyed.
12
+ # current_user - the user performing the action
13
+ def initialize(result, current_user)
14
+ @result = result
15
+ @current_user = current_user
16
+ end
17
+
18
+ # Destroys the result.
19
+ #
20
+ # Broadcasts :ok if successful, :invalid otherwise.
21
+ def call
22
+ destroy_result
23
+
24
+ broadcast(:ok)
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :result, :current_user
30
+
31
+ def destroy_result
32
+ Decidim.traceability.perform_action!(
33
+ :delete,
34
+ result,
35
+ current_user
36
+ ) do
37
+ result.destroy!
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -6,9 +6,9 @@ module Decidim
6
6
  # This controller is the abstract class from which all other controllers of
7
7
  # this engine inherit.
8
8
  #
9
- # Note that it inherits from `Decidim::Features::BaseController`, which
9
+ # Note that it inherits from `Decidim::Components::BaseController`, which
10
10
  # override its layout and provide all kinds of useful methods.
11
- class ApplicationController < Decidim::Admin::Features::BaseController
11
+ class ApplicationController < Decidim::Admin::Components::BaseController
12
12
  end
13
13
  end
14
14
  end
@@ -49,11 +49,13 @@ module Decidim
49
49
  end
50
50
 
51
51
  def destroy
52
- result.destroy!
53
-
54
- flash[:notice] = I18n.t("results.destroy.success", scope: "decidim.accountability.admin")
52
+ DestroyResult.call(result, current_user) do
53
+ on(:ok) do
54
+ flash[:notice] = I18n.t("results.destroy.success", scope: "decidim.accountability.admin")
55
55
 
56
- redirect_to results_path(parent_id: result.parent_id)
56
+ redirect_to results_path(parent_id: result.parent_id)
57
+ end
58
+ end
57
59
  end
58
60
 
59
61
  def proposals
@@ -63,7 +65,7 @@ module Decidim
63
65
  end
64
66
  format.json do
65
67
  query = Decidim.find_resource_manifest(:proposals)
66
- .try(:resource_scope, current_feature)&.order(title: :asc)
68
+ .try(:resource_scope, current_component)&.order(title: :asc)
67
69
  term = params[:term]
68
70
  if term&.start_with?("#")
69
71
  term.delete!("#")
@@ -80,23 +82,23 @@ module Decidim
80
82
 
81
83
  def results
82
84
  parent_id = params[:parent_id].presence
83
- @results ||= Result.where(feature: current_feature, parent_id: parent_id).page(params[:page]).per(15)
85
+ @results ||= Result.where(component: current_component, parent_id: parent_id).page(params[:page]).per(15)
84
86
  end
85
87
 
86
88
  def result
87
- @result ||= Result.where(feature: current_feature).find(params[:id])
89
+ @result ||= Result.where(component: current_component).find(params[:id])
88
90
  end
89
91
 
90
92
  def parent_result
91
- @parent_result ||= Result.where(feature: current_feature, id: params[:parent_id]).first
93
+ @parent_result ||= Result.find_by(component: current_component, id: params[:parent_id])
92
94
  end
93
95
 
94
96
  def parent_results
95
- @parent_results ||= Result.where(feature: current_feature, parent_id: nil)
97
+ @parent_results ||= Result.where(component: current_component, parent_id: nil)
96
98
  end
97
99
 
98
100
  def statuses
99
- @statuses ||= Status.where(feature: current_feature)
101
+ @statuses ||= Status.where(component: current_component)
100
102
  end
101
103
  end
102
104
  end
@@ -58,7 +58,7 @@ module Decidim
58
58
  private
59
59
 
60
60
  def statuses
61
- @statuses ||= Status.where(feature: current_feature).page(params[:page]).per(15)
61
+ @statuses ||= Status.where(component: current_component).page(params[:page]).per(15)
62
62
  end
63
63
 
64
64
  def status
@@ -67,7 +67,7 @@ module Decidim
67
67
  end
68
68
 
69
69
  def result
70
- @result ||= Result.where(feature: current_feature).find(params[:result_id])
70
+ @result ||= Result.where(component: current_component).find(params[:result_id])
71
71
  end
72
72
  end
73
73
  end
@@ -5,9 +5,9 @@ module Decidim
5
5
  # This controller is the abstract class from which all other controllers of
6
6
  # this engine inherit.
7
7
  #
8
- # Note that it inherits from `Decidim::Features::BaseController`, which
8
+ # Note that it inherits from `Decidim::Components::BaseController`, which
9
9
  # override its layout and provide all kinds of useful methods.
10
- class ApplicationController < Decidim::Features::BaseController
10
+ class ApplicationController < Decidim::Components::BaseController
11
11
  end
12
12
  end
13
13
  end
@@ -8,7 +8,7 @@ module Decidim
8
8
  private
9
9
 
10
10
  def model
11
- @model ||= Result.where(feature: params[:feature_id]).find(params[:result_id])
11
+ @model ||= Result.where(component: params[:component_id]).find(params[:result_id])
12
12
  end
13
13
 
14
14
  def iframe_url
@@ -19,7 +19,7 @@ module Decidim
19
19
  end
20
20
 
21
21
  def result
22
- @result ||= Result.includes(:timeline_entries).where(feature: current_feature).find(params[:id])
22
+ @result ||= Result.includes(:timeline_entries).where(component: current_component).find(params[:id])
23
23
  end
24
24
 
25
25
  def search_klass
@@ -35,7 +35,7 @@ module Decidim
35
35
  end
36
36
 
37
37
  def context_params
38
- { feature: current_feature, organization: current_organization }
38
+ { component: current_component, organization: current_organization }
39
39
  end
40
40
 
41
41
  def first_class_categories
@@ -43,7 +43,7 @@ module Decidim
43
43
  end
44
44
 
45
45
  def count_calculator(scope_id, category_id)
46
- Decidim::Accountability::ResultsCalculator.new(current_feature, scope_id, category_id).count
46
+ Decidim::Accountability::ResultsCalculator.new(current_component, scope_id, category_id).count
47
47
  end
48
48
  end
49
49
  end
@@ -12,7 +12,7 @@ module Decidim
12
12
  private
13
13
 
14
14
  def result
15
- @result ||= Result.includes(:timeline_entries).where(feature: current_feature).find(params[:result_id])
15
+ @result ||= Result.includes(:timeline_entries).where(component: current_component).find(params[:result_id])
16
16
  end
17
17
 
18
18
  def current_version
@@ -14,7 +14,7 @@ module Decidim
14
14
  end
15
15
 
16
16
  def proposal
17
- @proposal ||= resource.linked_resources(:proposals, "included_proposals").where(id: extra[:proposal_id]).first
17
+ @proposal ||= resource.linked_resources(:proposals, "included_proposals").find_by(id: extra[:proposal_id])
18
18
  end
19
19
  end
20
20
  end
@@ -32,7 +32,7 @@ module Decidim
32
32
 
33
33
  validate :scope_belongs_to_participatory_space_scope
34
34
 
35
- delegate :categories, to: :current_feature
35
+ delegate :categories, to: :current_component
36
36
 
37
37
  def map_model(model)
38
38
  self.proposal_ids = model.linked_resources(:proposals, "included_proposals").pluck(:id)
@@ -42,13 +42,13 @@ module Decidim
42
42
 
43
43
  def proposals
44
44
  @proposals ||= Decidim.find_resource_manifest(:proposals)
45
- .try(:resource_scope, current_feature)
45
+ .try(:resource_scope, current_component)
46
46
  &.where(id: proposal_ids)
47
47
  &.order(title: :asc)
48
48
  end
49
49
 
50
50
  def projects
51
- @projects ||= Decidim.find_resource_manifest(:projects).try(:resource_scope, current_feature)&.order(title: :asc)
51
+ @projects ||= Decidim.find_resource_manifest(:projects).try(:resource_scope, current_component)&.order(title: :asc)
52
52
  &.select(:title, :id)&.map { |a| [a.title[I18n.locale.to_s], a.id] }
53
53
  end
54
54
 
@@ -71,11 +71,11 @@ module Decidim
71
71
  end
72
72
 
73
73
  def parent
74
- @parent ||= Decidim::Accountability::Result.find_by(feature: current_feature, id: parent_id)
74
+ @parent ||= Decidim::Accountability::Result.find_by(component: current_component, id: parent_id)
75
75
  end
76
76
 
77
77
  def status
78
- @status ||= Decidim::Accountability::Status.find_by(feature: current_feature, id: decidim_accountability_status_id)
78
+ @status ||= Decidim::Accountability::Status.find_by(component: current_component, id: decidim_accountability_status_id)
79
79
  end
80
80
 
81
81
  private
@@ -23,15 +23,15 @@ module Decidim
23
23
  end
24
24
 
25
25
  def categories_label
26
- translated_attribute(feature_settings.categories_label).presence || t("results.home.categories_label", scope: "decidim.accountability")
26
+ translated_attribute(component_settings.categories_label).presence || t("results.home.categories_label", scope: "decidim.accountability")
27
27
  end
28
28
 
29
29
  def subcategories_label
30
- translated_attribute(feature_settings.subcategories_label).presence || t("results.home.subcategories_label", scope: "decidim.accountability")
30
+ translated_attribute(component_settings.subcategories_label).presence || t("results.home.subcategories_label", scope: "decidim.accountability")
31
31
  end
32
32
 
33
33
  def heading_parent_level_results(count)
34
- text = translated_attribute(feature_settings.heading_parent_level_results).presence
34
+ text = translated_attribute(component_settings.heading_parent_level_results).presence
35
35
  if text
36
36
  "#{count} #{text}"
37
37
  else
@@ -40,7 +40,7 @@ module Decidim
40
40
  end
41
41
 
42
42
  def heading_leaf_level_results(count)
43
- text = translated_attribute(feature_settings.heading_leaf_level_results).presence
43
+ text = translated_attribute(component_settings.heading_leaf_level_results).presence
44
44
  if text
45
45
  "#{count} #{text}"
46
46
  else
@@ -14,7 +14,7 @@ module Decidim
14
14
  end
15
15
 
16
16
  def progress_calculator(scope_id, category_id)
17
- Decidim::Accountability::ResultsCalculator.new(current_feature, scope_id, category_id).progress
17
+ Decidim::Accountability::ResultsCalculator.new(current_component, scope_id, category_id).progress
18
18
  end
19
19
 
20
20
  def category
@@ -6,14 +6,15 @@ module Decidim
6
6
  # title, description and any other useful information to render a custom result.
7
7
  class Result < Accountability::ApplicationRecord
8
8
  include Decidim::Resourceable
9
- include Decidim::HasFeature
10
- include Decidim::ScopableFeature
9
+ include Decidim::HasComponent
10
+ include Decidim::ScopableComponent
11
11
  include Decidim::HasCategory
12
12
  include Decidim::HasReference
13
13
  include Decidim::Comments::Commentable
14
14
  include Decidim::Traceable
15
+ include Decidim::Loggable
15
16
 
16
- feature_manifest_name "accountability"
17
+ component_manifest_name "accountability"
17
18
 
18
19
  has_many :children, foreign_key: "parent_id", class_name: "Decidim::Accountability::Result", inverse_of: :parent, dependent: :destroy
19
20
  belongs_to :parent, foreign_key: "parent_id", class_name: "Decidim::Accountability::Result", inverse_of: :children, optional: true, counter_cache: :children_count
@@ -32,6 +33,10 @@ module Decidim
32
33
  end
33
34
  end
34
35
 
36
+ def self.log_presenter_class_for(_log)
37
+ Decidim::Accountability::AdminLog::ResultPresenter
38
+ end
39
+
35
40
  def update_parent_progress
36
41
  return if parent.blank?
37
42
 
@@ -45,12 +50,12 @@ module Decidim
45
50
 
46
51
  # Public: Overrides the `commentable?` Commentable concern method.
47
52
  def commentable?
48
- feature.settings.comments_enabled?
53
+ component.settings.comments_enabled?
49
54
  end
50
55
 
51
56
  # Public: Overrides the `accepts_new_comments?` Commentable concern method.
52
57
  def accepts_new_comments?
53
- commentable? && !feature.current_settings.comments_blocked
58
+ commentable? && !component.current_settings.comments_blocked
54
59
  end
55
60
 
56
61
  # Public: Overrides the `comments_have_alignment?` Commentable concern method.
@@ -5,13 +5,13 @@ module Decidim
5
5
  # The data store for a Status in the Decidim::Accountability component. It stores a
6
6
  # key, a localized name, a localized description and and associated progress number.
7
7
  class Status < Accountability::ApplicationRecord
8
- include Decidim::HasFeature
8
+ include Decidim::HasComponent
9
9
 
10
- feature_manifest_name "accountability"
10
+ component_manifest_name "accountability"
11
11
 
12
12
  has_many :results, foreign_key: "decidim_accountability_status_id", class_name: "Decidim::Accountability::Result", inverse_of: :status, dependent: :nullify
13
13
 
14
- validates :key, presence: true, uniqueness: { scope: :decidim_feature_id }
14
+ validates :key, presence: true, uniqueness: { scope: :decidim_component_id }
15
15
  validates :name, presence: true
16
16
  end
17
17
  end