decidim-core 0.4.3 → 0.4.4

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/decidim/modules/_card-grid.scss +2 -2
  3. data/app/assets/stylesheets/decidim/modules/_filters.scss +3 -3
  4. data/app/assets/stylesheets/decidim/modules/_main-container.scss +1 -5
  5. data/app/assets/stylesheets/decidim/modules/_process-nav.scss +1 -2
  6. data/app/constraints/decidim/current_participatory_process.rb +1 -1
  7. data/app/controllers/concerns/decidim/needs_authorization.rb +2 -3
  8. data/app/controllers/concerns/decidim/needs_participatory_process.rb +1 -1
  9. data/app/controllers/concerns/decidim/{feature_settings.rb → settings.rb} +1 -1
  10. data/app/controllers/decidim/features/base_controller.rb +1 -2
  11. data/app/controllers/decidim/pages_controller.rb +1 -1
  12. data/app/helpers/decidim/feature_path_helper.rb +1 -1
  13. data/{lib → app/models}/decidim/abilities/admin_ability.rb +1 -0
  14. data/app/models/decidim/abilities/base_ability.rb +34 -0
  15. data/{lib → app/models}/decidim/abilities/participatory_process_admin_ability.rb +4 -0
  16. data/{lib → app/models}/decidim/abilities/participatory_process_collaborator_ability.rb +4 -0
  17. data/{lib → app/models}/decidim/abilities/participatory_process_moderator_ability.rb +0 -0
  18. data/app/models/decidim/feature.rb +3 -78
  19. data/app/models/decidim/organization.rb +0 -2
  20. data/app/models/decidim/participatory_process.rb +2 -16
  21. data/app/models/decidim/participatory_process_group.rb +1 -2
  22. data/app/models/decidim/participatory_process_user_role.rb +9 -0
  23. data/app/models/decidim/user.rb +0 -7
  24. data/app/presenters/decidim/home_stats_presenter.rb +1 -1
  25. data/app/presenters/decidim/resource_locator_presenter.rb +57 -15
  26. data/app/queries/decidim/highlighted_participatory_processes.rb +1 -2
  27. data/app/queries/decidim/organization_participatory_process_groups.rb +14 -0
  28. data/app/queries/decidim/organization_participatory_processes.rb +2 -6
  29. data/app/queries/decidim/organization_prioritized_participatory_processes.rb +3 -3
  30. data/app/queries/decidim/organization_published_participatory_processes.rb +17 -0
  31. data/app/queries/decidim/participatory_processes_with_user_role.rb +1 -1
  32. data/app/queries/decidim/prioritized_participatory_processes.rb +1 -1
  33. data/app/queries/decidim/published_participatory_processes.rb +10 -0
  34. data/app/views/layouts/decidim/_process_header.html.erb +2 -2
  35. data/config/locales/ca.yml +19 -0
  36. data/config/locales/es.yml +19 -0
  37. data/config/locales/fr.yml +2 -2
  38. data/db/migrate/20170608142521_add_organization_to_user_groups.rb +16 -3
  39. data/db/seeds.rb +17 -12
  40. data/lib/decidim/abilities.rb +0 -4
  41. data/lib/decidim/abilities/participatory_process_role_ability.rb +4 -1
  42. data/lib/decidim/core.rb +20 -20
  43. data/lib/decidim/core/api/decidim_type.rb +1 -1
  44. data/lib/decidim/core/api/process_step_type.rb +2 -2
  45. data/lib/decidim/core/api/process_type.rb +1 -1
  46. data/lib/decidim/core/api/session_type.rb +1 -1
  47. data/lib/decidim/core/api/translated_field_type.rb +3 -3
  48. data/lib/decidim/core/test.rb +1 -0
  49. data/lib/decidim/core/test/factories.rb +21 -2
  50. data/lib/decidim/core/test/shared_examples/publicable.rb +27 -0
  51. data/lib/decidim/core/version.rb +1 -1
  52. data/lib/decidim/feature_manifest.rb +6 -6
  53. data/lib/decidim/form_builder.rb +1 -1
  54. data/lib/decidim/has_category.rb +1 -1
  55. data/lib/decidim/has_settings.rb +66 -0
  56. data/lib/decidim/manifest_registry.rb +45 -0
  57. data/lib/decidim/publicable.rb +49 -0
  58. data/lib/decidim/query_extensions.rb +1 -1
  59. data/lib/decidim/reportable.rb +3 -3
  60. data/lib/decidim/{features/settings_manifest.rb → settings_manifest.rb} +5 -5
  61. metadata +26 -33
  62. data/app/models/decidim/ability.rb +0 -32
@@ -13,7 +13,10 @@ module Decidim
13
13
  # Define abilities if the user is not an admin and has at least one process to manage.
14
14
  if not_admin? && has_manageable_processes?
15
15
  define_abilities
16
- define_participatory_process_abilities if current_participatory_process && can_manage_process?(current_participatory_process)
16
+
17
+ if current_participatory_process && can_manage_process?(current_participatory_process)
18
+ define_participatory_process_abilities
19
+ end
17
20
  end
18
21
  end
19
22
 
data/lib/decidim/core.rb CHANGED
@@ -18,9 +18,11 @@ module Decidim
18
18
  autoload :Reportable, "decidim/reportable"
19
19
  autoload :Authorable, "decidim/authorable"
20
20
  autoload :Notifiable, "decidim/notifiable"
21
+ autoload :Publicable, "decidim/publicable"
21
22
  autoload :Features, "decidim/features"
22
23
  autoload :HasAttachments, "decidim/has_attachments"
23
24
  autoload :FeatureValidator, "decidim/feature_validator"
25
+ autoload :HasSettings, "decidim/has_settings"
24
26
  autoload :HasFeature, "decidim/has_feature"
25
27
  autoload :HasScope, "decidim/has_scope"
26
28
  autoload :HasCategory, "decidim/has_category"
@@ -32,6 +34,7 @@ module Decidim
32
34
  autoload :Menu, "decidim/menu"
33
35
  autoload :MenuItem, "decidim/menu_item"
34
36
  autoload :MenuRegistry, "decidim/menu_registry"
37
+ autoload :ManifestRegistry, "decidim/manifest_registry"
35
38
  autoload :Abilities, "decidim/abilities"
36
39
 
37
40
  include ActiveSupport::Configurable
@@ -49,7 +52,11 @@ module Decidim
49
52
  railtie.load_seed
50
53
  end
51
54
 
52
- Decidim.feature_manifests.each(&:seed!)
55
+ Decidim::ParticipatoryProcess.find_each do |process|
56
+ Decidim.feature_manifests.each do |feature|
57
+ feature.seed!(process)
58
+ end
59
+ end
53
60
 
54
61
  I18n.available_locales = original_locale
55
62
  end
@@ -62,7 +69,8 @@ module Decidim
62
69
  config_accessor :mailer_sender
63
70
 
64
71
  # Exposes a configuration option: an Array of `cancancan`'s Ability classes
65
- # that will be automatically included to the base `Decidim::Ability` class.
72
+ # that will be automatically included to the base `Decidim::Abilities::BaseAbility`
73
+ # class.
66
74
  config_accessor :abilities do
67
75
  []
68
76
  end
@@ -138,19 +146,16 @@ module Decidim
138
146
  # name - A Symbol with the feature's unique name.
139
147
  #
140
148
  # Returns nothing.
141
- def self.register_feature(name)
142
- manifest = FeatureManifest.new(name: name.to_sym)
143
- yield(manifest)
144
- manifest.validate!
145
- feature_manifests << manifest
149
+ def self.register_feature(name, &block)
150
+ feature_registry.register(name, &block)
146
151
  end
147
152
 
148
- # Public: Finds all the registered feature manifest's via the
149
- # `register_feature` method.
153
+ # Public: Finds all registered feature manifest's via the `register_feature`
154
+ # method.
150
155
  #
151
156
  # Returns an Array[FeatureManifest].
152
157
  def self.feature_manifests
153
- @feature_manifests ||= Set.new
158
+ feature_registry.manifests
154
159
  end
155
160
 
156
161
  # Public: Finds a feature manifest by the feature's name.
@@ -159,8 +164,7 @@ module Decidim
159
164
  #
160
165
  # Returns a FeatureManifest if found, nil otherwise.
161
166
  def self.find_feature_manifest(name)
162
- name = name.to_sym
163
- feature_manifests.find { |manifest| manifest.name == name }
167
+ feature_registry.find(name.to_sym)
164
168
  end
165
169
 
166
170
  # Public: Finds a resource manifest by the resource's name.
@@ -170,16 +174,12 @@ module Decidim
170
174
  #
171
175
  # Returns a ResourceManifest if found, nil otherwise.
172
176
  def self.find_resource_manifest(resource_name_or_klass)
173
- resource_manifests.find do |manifest|
174
- manifest.model_class == resource_name_or_klass || manifest.name.to_s == resource_name_or_klass.to_s
175
- end
177
+ feature_registry.find_resource_manifest(resource_name_or_klass)
176
178
  end
177
179
 
178
- # Private: Stores all the resource manifest across all feature manifest.
179
- #
180
- # Returns an Array[ResourceManifest]
181
- def self.resource_manifests
182
- @resource_manifests ||= feature_manifests.flat_map(&:resource_manifests)
180
+ # Public: Stores the registry of features
181
+ def self.feature_registry
182
+ @feature_registry ||= ManifestRegistry.new(:features)
183
183
  end
184
184
 
185
185
  # Public: Stores an instance of StatsRegistry
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Decidim
4
- # This type represents a ParticipatoryProcess.
4
+ # This type represents a Decidim's global property.
5
5
  DecidimType = GraphQL::ObjectType.define do
6
6
  name "Decidim"
7
7
  description "Decidim's framework-related properties."
@@ -9,11 +9,11 @@ module Decidim
9
9
  field :id, !types.ID, "The unique ID of this step."
10
10
 
11
11
  field :process do
12
- type ProcessType
12
+ type !ProcessType
13
13
  description "The participatory process in which this step belongs to."
14
14
  property :participatory_process
15
15
  end
16
16
 
17
- field :title, TranslatedFieldType, "The title of this step"
17
+ field :title, !TranslatedFieldType, "The title of this step"
18
18
  end
19
19
  end
@@ -8,7 +8,7 @@ module Decidim
8
8
 
9
9
  field :id, !types.ID, "The Process' unique ID"
10
10
 
11
- field :title, TranslatedFieldType, "The title of this process."
11
+ field :title, !TranslatedFieldType, "The title of this process."
12
12
 
13
13
  connection :steps, ProcessStepType.connection_type do
14
14
  description "All the steps of this process."
@@ -10,7 +10,7 @@ module Decidim
10
10
  resolve ->(obj, _args, _ctx) { obj }
11
11
  end
12
12
 
13
- field :verifiedUserGroups, !types[UserGroupType], "The current user verified user groups" do
13
+ field :verifiedUserGroups, !types[!UserGroupType], "The current user verified user groups" do
14
14
  resolve ->(obj, _args, _ctx) { obj.user_groups.verified }
15
15
  end
16
16
  end
@@ -7,17 +7,17 @@ module Decidim
7
7
  description "A translated field"
8
8
 
9
9
  field :locales do
10
- type types[types.String]
10
+ type types[!types.String]
11
11
  description "Lists all the locales in which this translation is available"
12
12
  resolve ->(obj, _args, _ctx) { obj.keys }
13
13
  end
14
14
 
15
15
  field :translations do
16
- type !types[LocalizedStringType]
16
+ type !types[!LocalizedStringType]
17
17
  description "All the localized strings for this translation."
18
18
 
19
19
  argument :locales do
20
- type types[types.String]
20
+ type types[!types.String]
21
21
  description "A list of locales to scope the translations to."
22
22
  end
23
23
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "decidim/core/test/shared_examples/authorable"
4
+ require "decidim/core/test/shared_examples/publicable"
4
5
  require "decidim/core/test/shared_examples/localised_email"
5
6
  require "decidim/core/test/shared_examples/has_attachments"
6
7
  require "decidim/core/test/shared_examples/has_feature"
@@ -153,7 +153,11 @@ FactoryGirl.define do
153
153
  end
154
154
 
155
155
  trait :process_admin do
156
- transient { participatory_process nil }
156
+ transient do
157
+ participatory_process { create(:participatory_process) }
158
+ end
159
+
160
+ organization { participatory_process.organization }
157
161
 
158
162
  after(:create) do |user, evaluator|
159
163
  create :participatory_process_user_role,
@@ -162,11 +166,26 @@ FactoryGirl.define do
162
166
  role: :admin
163
167
  end
164
168
  end
169
+
170
+ trait :process_collaborator do
171
+ transient do
172
+ participatory_process { create(:participatory_process) }
173
+ end
174
+
175
+ organization { participatory_process.organization }
176
+
177
+ after(:create) do |user, evaluator|
178
+ create :participatory_process_user_role,
179
+ user: user,
180
+ participatory_process: evaluator.participatory_process,
181
+ role: :collaborator
182
+ end
183
+ end
165
184
  end
166
185
 
167
186
  factory :participatory_process_user_role, class: Decidim::ParticipatoryProcessUserRole do
168
187
  user
169
- participatory_process
188
+ participatory_process { create :participatory_process, organization: user.organization }
170
189
  role "admin"
171
190
  end
172
191
 
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ shared_examples_for "publicable" do
6
+ let(:factory_name) { described_class.name.demodulize.underscore.to_sym }
7
+
8
+ let!(:published) do
9
+ create(factory_name, published_at: Time.zone.now)
10
+ end
11
+
12
+ let!(:unpublished) do
13
+ create(factory_name, published_at: nil)
14
+ end
15
+
16
+ describe ".published" do
17
+ let(:scope) { described_class.send(:published) }
18
+
19
+ it { expect(scope).to eq([published]) }
20
+ end
21
+
22
+ describe ".unpublished" do
23
+ let(:scope) { described_class.send(:unpublished) }
24
+
25
+ it { expect(scope).to eq([unpublished]) }
26
+ end
27
+ end
@@ -3,7 +3,7 @@
3
3
  # This holds Decidim's version and the Rails version on which it depends.
4
4
  module Decidim
5
5
  def self.version
6
- "0.4.3"
6
+ "0.4.4"
7
7
  end
8
8
 
9
9
  def self.rails_version
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "decidim/features/settings_manifest"
3
+ require "decidim/settings_manifest"
4
4
  require "decidim/features/export_manifest"
5
5
 
6
6
  module Decidim
@@ -92,15 +92,15 @@ module Decidim
92
92
  # Public: Creates the seeds for this features in order to populate the database.
93
93
  #
94
94
  # Returns nothing.
95
- def seed!
96
- @seeds&.call
95
+ def seed!(process)
96
+ @seeds&.call(process)
97
97
  end
98
98
 
99
99
  # Public: Adds configurable attributes for this feature, scoped to a name. It
100
- # uses the DSL specified under `Decidim::FeatureSettingsManifest`.
100
+ # uses the DSL specified under `Decidim::SettingsManifest`.
101
101
  #
102
102
  # name - Either `global` or `step`
103
- # &block - The DSL present on `Decidim::FeatureSettingsManifest`
103
+ # &block - The DSL present on `Decidim::SettingsManifest`
104
104
  #
105
105
  # Examples:
106
106
  #
@@ -112,7 +112,7 @@ module Decidim
112
112
  def settings(name = :global, &block)
113
113
  @settings ||= {}
114
114
  name = name.to_sym
115
- settings = (@settings[name] ||= FeatureSettingsManifest.new)
115
+ settings = (@settings[name] ||= SettingsManifest.new)
116
116
  yield(settings) if block
117
117
  settings
118
118
  end
@@ -161,7 +161,7 @@ module Decidim
161
161
  # datepicker library
162
162
  def datetime_field(attribute, options = {})
163
163
  value = object.send(attribute)
164
- if value
164
+ if value.present?
165
165
  iso_value = value.strftime("%Y-%m-%dT%H:%M:%S")
166
166
  formatted_value = I18n.localize(value, format: :timepicker)
167
167
  end
@@ -3,7 +3,7 @@
3
3
  require "active_support/concern"
4
4
 
5
5
  module Decidim
6
- # A concern with the features needed when you want a model to be have a category.
6
+ # A concern with the features needed when you want a model to have a category.
7
7
  module HasCategory
8
8
  extend ActiveSupport::Concern
9
9
 
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ module HasSettings
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ after_initialize :default_values
11
+ end
12
+
13
+ def settings
14
+ settings_schema(:global).new(self[:settings]["global"])
15
+ end
16
+
17
+ def settings=(data)
18
+ self[:settings]["global"] = serialize_settings(settings_schema(:global), data)
19
+ end
20
+
21
+ def default_step_settings
22
+ settings_schema(:step).new(self[:settings]["default_step"])
23
+ end
24
+
25
+ def default_step_settings=(data)
26
+ self[:settings]["default_step"] = serialize_settings(settings_schema(:step), data)
27
+ end
28
+
29
+ def step_settings
30
+ participatory_process.steps.each_with_object({}) do |step, result|
31
+ result[step.id.to_s] = settings_schema(:step).new(self[:settings].dig("steps", step.id.to_s))
32
+ end
33
+ end
34
+
35
+ def step_settings=(data)
36
+ self[:settings]["steps"] = data.each_with_object({}) do |(key, value), result|
37
+ result[key.to_s] = serialize_settings(settings_schema(:step), value)
38
+ end
39
+ end
40
+
41
+ def active_step_settings
42
+ active_step = participatory_process.active_step
43
+ return default_step_settings unless active_step
44
+
45
+ step_settings.fetch(active_step.id.to_s)
46
+ end
47
+
48
+ private
49
+
50
+ def serialize_settings(schema, value)
51
+ if value.respond_to?(:attributes)
52
+ value.attributes
53
+ else
54
+ schema.new(value)
55
+ end
56
+ end
57
+
58
+ def settings_schema(name)
59
+ manifest.settings(name.to_sym).schema
60
+ end
61
+
62
+ def default_values
63
+ self[:settings] ||= {}
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ #
5
+ # Takes care of holding and serving globally registered manifests.
6
+ #
7
+ class ManifestRegistry
8
+ def initialize(entity)
9
+ @entity = entity
10
+ end
11
+
12
+ def register(name)
13
+ manifest = manifest_class.new(name: name.to_sym)
14
+ yield(manifest)
15
+ manifest.validate!
16
+ manifests << manifest
17
+ end
18
+
19
+ def manifests
20
+ @manifests ||= Set.new
21
+ end
22
+
23
+ def find(name)
24
+ manifests.find { |manifest| manifest.name == name }
25
+ end
26
+
27
+ def resource_manifests
28
+ @resource_manifests ||= manifests.flat_map(&:resource_manifests)
29
+ end
30
+
31
+ def find_resource_manifest(resource_name_or_klass)
32
+ resource_manifests.find do |manifest|
33
+ manifest.model_class == resource_name_or_klass || manifest.name.to_s == resource_name_or_klass.to_s
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def manifest_class
40
+ case @entity
41
+ when :features then FeatureManifest
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ # This concern contains the logic related to publication and promotion.
7
+ module Publicable
8
+ extend ActiveSupport::Concern
9
+
10
+ class_methods do
11
+ # Public: Scope to return only published records.
12
+ #
13
+ # Returns an ActiveRecord::Relation.
14
+ def published
15
+ where.not(published_at: nil)
16
+ end
17
+
18
+ # Public: Scope to return only unpublished records.
19
+ #
20
+ # Returns an ActiveRecord::Relation.
21
+ def unpublished
22
+ where(published_at: nil)
23
+ end
24
+ end
25
+
26
+ # Public: Checks whether the record has been published or not.
27
+ #
28
+ # Returns true if published, false otherwise.
29
+ def published?
30
+ published_at.present?
31
+ end
32
+
33
+ #
34
+ # Public: Publishes this feature
35
+ #
36
+ # Returns true if the record was properly saved, false otherwise.
37
+ def publish!
38
+ update_attribute(:published_at, Time.current)
39
+ end
40
+
41
+ #
42
+ # Public: Unpublishes this feature
43
+ #
44
+ # Returns true if the record was properly saved, false otherwise.
45
+ def unpublish!
46
+ update_attribute(:published_at, nil)
47
+ end
48
+ end
49
+ end