decidim-decidim_awesome 0.6.4 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -6
  3. data/app/assets/stylesheets/decidim/decidim_awesome/admin.scss +4 -0
  4. data/app/awesome_overrides/presenters/decidim/menu_presenter_override.rb +31 -0
  5. data/app/commands/decidim/decidim_awesome/admin/create_menu_hack.rb +51 -0
  6. data/app/commands/decidim/decidim_awesome/admin/destroy_menu_hack.rb +47 -0
  7. data/app/commands/decidim/decidim_awesome/admin/update_config.rb +1 -1
  8. data/app/commands/decidim/decidim_awesome/admin/update_menu_hack.rb +47 -0
  9. data/app/controllers/decidim/decidim_awesome/admin/application_controller.rb +4 -3
  10. data/app/controllers/decidim/decidim_awesome/admin/config_controller.rb +9 -0
  11. data/app/controllers/decidim/decidim_awesome/admin/constraints_controller.rb +13 -0
  12. data/app/controllers/decidim/decidim_awesome/admin/menu_hacks_controller.rb +116 -0
  13. data/app/forms/decidim/decidim_awesome/admin/config_form.rb +5 -7
  14. data/app/forms/decidim/decidim_awesome/admin/constraint_form.rb +0 -2
  15. data/app/forms/decidim/decidim_awesome/admin/intergram_form.rb +0 -2
  16. data/app/forms/decidim/decidim_awesome/admin/menu_form.rb +39 -0
  17. data/app/helpers/decidim/decidim_awesome/admin/config_constraints_helpers.rb +5 -1
  18. data/app/permissions/decidim/decidim_awesome/admin/permissions.rb +19 -0
  19. data/app/permissions/decidim/decidim_awesome/permissions.rb +2 -0
  20. data/app/views/decidim/decidim_awesome/admin/config/_form_styles.html.erb +0 -1
  21. data/app/views/decidim/decidim_awesome/admin/menu_hacks/_form.html.erb +7 -0
  22. data/app/views/decidim/decidim_awesome/admin/menu_hacks/edit.html.erb +13 -0
  23. data/app/views/decidim/decidim_awesome/admin/menu_hacks/index.html.erb +44 -0
  24. data/app/views/decidim/decidim_awesome/admin/menu_hacks/new.html.erb +13 -0
  25. data/app/views/layouts/decidim/admin/decidim_awesome.html.erb +5 -0
  26. data/config/locales/ca.yml +45 -4
  27. data/config/locales/cs.yml +46 -5
  28. data/config/locales/en.yml +47 -4
  29. data/config/locales/es.yml +45 -4
  30. data/config/locales/eu.yml +45 -4
  31. data/config/locales/fr.yml +45 -4
  32. data/config/locales/nl.yml +212 -0
  33. data/config/locales/sv.yml +45 -4
  34. data/lib/decidim/decidim_awesome.rb +15 -0
  35. data/lib/decidim/decidim_awesome/admin_engine.rb +1 -0
  36. data/lib/decidim/decidim_awesome/checksums.yml +6 -0
  37. data/lib/decidim/decidim_awesome/engine.rb +1 -1
  38. data/lib/decidim/decidim_awesome/menu_hacker.rb +88 -0
  39. data/lib/decidim/decidim_awesome/test/shared_examples/config_examples.rb +4 -2
  40. data/lib/decidim/decidim_awesome/test/shared_examples/menu_hack_contexts.rb +71 -0
  41. data/lib/decidim/decidim_awesome/version.rb +1 -1
  42. metadata +16 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca4e9a5883518e03b29844b430fe92343558ca88394a4e03334ebb387cf133dc
4
- data.tar.gz: 2dbdc12ff4446debcf62641c8dc4fa788fc5a07011060216874d3811f526d4f5
3
+ metadata.gz: 2be39606cbd0f92bc8232bbd4a1c8b04a27aed18e9a0732668af6f37126d66f4
4
+ data.tar.gz: 5034f9d65042871ec4be47c313e90c46390e40751003666ea8a93166df087d31
5
5
  SHA512:
6
- metadata.gz: eb94d6bb293ebf2ac77767d18721f7f59f674a6fcfa89b5d8c3a12b7a2c56f3c49629767e878ff0ef7c9f7dffb31b13c1a90c7d82e5ffea2893aa1d59b57b548
7
- data.tar.gz: 1af64bdf1c90aa1bcfb296777726df9fe7ffe6e1b472cd057e2595376b9eac47e96bd3c3abc4a6ebc2aba20537ecaac4c6047f8d2d0039ed436b33bdfbac2f6f
6
+ metadata.gz: b2219e00f0a35206d772032e1f259e5283e2085a39bf5f45e47af09a784ece3776c0824ed7dc6d191cdcbf036b34a647fb5c9c172e13f86ef21394f54275fc9a
7
+ data.tar.gz: e2abb579c41c61b11377c986f692cba8b944671e1876616bf771309b8e62900a05b57582f72f1f458ef17309b55d8030c15727993ad99092c40ac4c4e31fd94a
data/README.md CHANGED
@@ -33,7 +33,7 @@ Each hack can be scoped to one or more specific participatory spaces or componen
33
33
 
34
34
  #### 1. Image support for the Quill editor
35
35
 
36
- Modifies the WYSIWYG editor in Decidim by adding the possibility to insert images. When uploading images, Drag & Drop is supported. Images will be uploaded to the server and inserted as external resources (it doesn't use base64 inline encoding).
36
+ Modifies the WYSIWYG editor in Decidim by adding the possibility to insert images. When uploading images, Drag & Drop is supported. Images will be uploaded to the server and inserted as external resources (it doesn't use base64 in-line encoding).
37
37
 
38
38
  This feature allows you use images in newsletters as well.
39
39
 
@@ -71,13 +71,13 @@ Many scopes can be defined for every tweak.
71
71
 
72
72
  This is a component you can add in any participatory space. It retrieves all the geolocated content in that participatory space (meetings or proposals) and displays it in a big map.
73
73
 
74
- It also provides a simple search by category, each category is assignated to a different color.
74
+ It also provides a simple search by category, each category is assigned to a different color.
75
75
 
76
76
  ![Awesome map](examples/awesome-map.png)
77
77
 
78
78
  #### 7. Allow Decidim to use custom CSS themes for every tenant
79
79
 
80
- When customizind CSS for a Decidim installation, each change affects all the organizations (tenant).
80
+ When customizing CSS for a Decidim installation, each change affects all the organizations (tenant).
81
81
 
82
82
  This feature allows to customize each organization css without affecting the others in the same Decidim installation.
83
83
 
@@ -106,12 +106,20 @@ With this feature you can have a support chat in Decidim. It is linked to a [Tel
106
106
 
107
107
  ![Intergram screenshot](examples/intergram.png)
108
108
 
109
- #### 10. Custom CSS applied only according scopes restrictions
109
+ #### 10. Custom CSS applied only according scoped restrictions
110
110
 
111
- For instance, with this feature you can create directly from the admin a CSS snipped that is only applied globally, in a particular assembly or even a single proposal!
111
+ With this feature you can create directly in the admin a CSS snipped that is only applied globally, in a particular assembly or even a single proposal!
112
112
 
113
113
  ![CSS screenshot](examples/custom_styles.png)
114
114
 
115
+ #### 11. Change the main menu of Decidim entirely!
116
+
117
+ Feel free to hide, modify or add items in the Decidim's main menu. You can also change the order, establish some conditions (like showing only for logged users) or open in a new window.
118
+
119
+ ![Menu hacks screenshot](examples/menu-1.png)
120
+ ![Menu hacks screenshot](examples/menu-2.png)
121
+ ![Menu hacks screenshot](examples/menu-3.png)
122
+ ![Menu hacks screenshot](examples/menu-4.png)
115
123
 
116
124
  #### To be continued...
117
125
 
@@ -127,7 +135,7 @@ Some things in the road-map:
127
135
  Add this line to your application's Gemfile:
128
136
 
129
137
  ```ruby
130
- gem "decidim-decidim_awesome", "~> 0.6.4"
138
+ gem "decidim-decidim_awesome", "~> 0.6.5"
131
139
  ```
132
140
 
133
141
  And then execute:
@@ -43,3 +43,7 @@
43
43
  padding-bottom: 0;
44
44
  }
45
45
  }
46
+
47
+ tbody tr.menu_hack-addition {
48
+ background: rgb(255, 248, 222);
49
+ }
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ Decidim::MenuPresenter.class_eval do
4
+ def evaluated_menu
5
+ @evaluated_menu ||= if Decidim::DecidimAwesome.config.send(@name) == :disabled
6
+ begin
7
+ menu = Decidim::Menu.new(@name)
8
+ menu.build_for(@view)
9
+ menu
10
+ end
11
+ else
12
+ Decidim::DecidimAwesome::MenuHacker.new(@name, @view)
13
+ end
14
+ end
15
+ end
16
+
17
+ Decidim::MenuItemPresenter.class_eval do
18
+ def link_to(name = nil, options = nil, html_options = nil, &block)
19
+ html_options ||= {}
20
+ html_options[:target] = @menu_item.try(:target)
21
+
22
+ options ||= html_options
23
+ @view.link_to(name, options, html_options, &block)
24
+ end
25
+
26
+ def active
27
+ return @menu_item.active.call(url, @view) if @menu_item.try(:active).respond_to?(:call)
28
+
29
+ @menu_item&.active
30
+ end
31
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ module Admin
6
+ class CreateMenuHack < Rectify::Command
7
+ # Public: Initializes the command.
8
+ #
9
+ def initialize(form, menu_name)
10
+ @form = form
11
+ @menu = AwesomeConfig.find_or_initialize_by(var: menu_name, organization: form.current_organization)
12
+ end
13
+
14
+ # Executes the command. Broadcasts these events:
15
+ #
16
+ # - :ok when everything is valid.
17
+ # - :invalid if we couldn't proceed.
18
+ #
19
+ # Returns nothing.
20
+ def call
21
+ return broadcast(:invalid) if form.invalid?
22
+ return broadcast(:invalid, I18n.t("menu_hacks.url_exists", scope: "decidim.decidim_awesome.admin")) if url_exists?
23
+
24
+ menu.value = [] unless menu.value.is_a? Array
25
+ menu.value << to_params
26
+ menu.save!
27
+ broadcast(:ok, menu)
28
+ rescue StandardError => e
29
+ broadcast(:invalid, e.message)
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :form, :menu
35
+
36
+ def url_exists?
37
+ return false unless menu
38
+
39
+ menu.value&.detect { |i| i["url"] == form.url.gsub(/\?.*/, "") }
40
+ end
41
+
42
+ def to_params
43
+ params = form.to_params
44
+ url = Addressable::URI.parse(params[:url])
45
+ params[:url] = url.path if url.host == form.current_organization.host
46
+ params
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ module Admin
6
+ class DestroyMenuHack < Rectify::Command
7
+ # Public: Initializes the command.
8
+ #
9
+ # item - the menu item to destroy
10
+ # organization
11
+ def initialize(item, menu_name, organization)
12
+ @item = item
13
+ @organization = organization
14
+ @menu = AwesomeConfig.find_by(var: menu_name, organization: organization)
15
+ end
16
+
17
+ # Executes the command. Broadcasts these events:
18
+ #
19
+ # - :ok when everything is valid.
20
+ # - :invalid if we couldn't proceed.
21
+ #
22
+ # Returns nothing.
23
+ def call
24
+ return broadcast(:invalid) unless url_exists?
25
+
26
+ menu.value&.reject! { |i| i["url"] == item.url }
27
+ menu.save!
28
+
29
+ broadcast(:ok, @item)
30
+ rescue StandardError => e
31
+ broadcast(:invalid, e.message)
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :organization, :item, :menu
37
+
38
+ def url_exists?
39
+ return false unless menu
40
+ return false unless menu.value.is_a? Array
41
+
42
+ menu.value&.detect { |i| i["url"] == item.url }
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -23,7 +23,7 @@ module Decidim
23
23
  begin
24
24
  form.attributes.each do |key, val|
25
25
  # ignore nil attributes (must specifically be set to false if necessary)
26
- next if val.nil?
26
+ next unless form.valid_keys.include?(key)
27
27
 
28
28
  setting = AwesomeConfig.find_or_initialize_by(var: key, organization: form.current_organization)
29
29
 
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ module Admin
6
+ class UpdateMenuHack < Rectify::Command
7
+ # Public: Initializes the command.
8
+ #
9
+ def initialize(form, menu_name)
10
+ @form = form
11
+ @menu = AwesomeConfig.find_or_initialize_by(var: menu_name, organization: form.current_organization)
12
+ end
13
+
14
+ # Executes the command. Broadcasts these events:
15
+ #
16
+ # - :ok when everything is valid.
17
+ # - :invalid if we couldn't proceed.
18
+ #
19
+ # Returns nothing.
20
+ def call
21
+ return broadcast(:invalid) if form.invalid?
22
+
23
+ menu.value = [] unless menu.value.is_a? Array
24
+ menu.value = menu.value.filter { |i| i.is_a? Hash }
25
+ found = false
26
+ menu.value.map! do |item|
27
+ if item["url"] == form.url
28
+ found = true
29
+ form.to_params
30
+ else
31
+ item
32
+ end
33
+ end
34
+ menu.value << form.to_params unless found
35
+ menu.save!
36
+ broadcast(:ok, menu)
37
+ rescue StandardError => e
38
+ broadcast(:invalid, e.message)
39
+ end
40
+
41
+ private
42
+
43
+ attr_reader :form, :menu
44
+ end
45
+ end
46
+ end
47
+ end
@@ -9,9 +9,10 @@ module Decidim
9
9
  # Note that it inherits from `Decidim::Admin::Components::BaseController`, which
10
10
  # override its layout and provide all kinds of useful methods.
11
11
  class ApplicationController < Decidim::Admin::ApplicationController
12
- # def permission_class_chain
13
- # [::Decidim::DecidimAwesome::Admin::Permissions] + super
14
- # end
12
+ def permission_class_chain
13
+ [::Decidim::DecidimAwesome::Admin::Permissions] + super
14
+ end
15
+
15
16
  before_action do
16
17
  enforce_permission_to :update, :organization, organization: current_organization
17
18
  end
@@ -12,6 +12,9 @@ module Decidim
12
12
  layout "decidim/admin/decidim_awesome"
13
13
 
14
14
  helper_method :constraints_for
15
+ before_action do
16
+ enforce_permission_to :edit_config, configs
17
+ end
15
18
 
16
19
  def show
17
20
  @form = form(ConfigForm).from_params(organization_awesome_config)
@@ -65,6 +68,12 @@ module Decidim
65
68
  def constraints_for(key)
66
69
  awesome_config_instance.setting_for(key)&.constraints
67
70
  end
71
+
72
+ def configs
73
+ return params[:config].keys if params.has_key?(:config)
74
+
75
+ DecidimAwesome.config.keys
76
+ end
68
77
  end
69
78
  end
70
79
  end
@@ -9,6 +9,9 @@ module Decidim
9
9
  helper ConfigConstraintsHelpers
10
10
 
11
11
  layout false
12
+ before_action do
13
+ enforce_permission_to :edit_config, constraint_key
14
+ end
12
15
 
13
16
  def new
14
17
  @form = form(ConstraintForm).from_params(filtered_params, setting: current_setting)
@@ -118,6 +121,16 @@ module Decidim
118
121
  def current_setting
119
122
  awesome_config_instance.setting_for params[:key]
120
123
  end
124
+
125
+ def constraint_key
126
+ key = params[:key] || constraint.awesome_config.var
127
+ case key
128
+ when /^scoped_style_/
129
+ :scoped_styles
130
+ else
131
+ key
132
+ end
133
+ end
121
134
  end
122
135
  end
123
136
  end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ module Admin
6
+ # Editing menu items
7
+ class MenuHacksController < DecidimAwesome::Admin::ApplicationController
8
+ include NeedsAwesomeConfig
9
+ helper ConfigConstraintsHelpers
10
+
11
+ layout "decidim/admin/decidim_awesome"
12
+
13
+ helper_method :current_items, :md5, :visibility_options, :target_options
14
+
15
+ before_action do
16
+ enforce_permission_to :edit_config, :menu
17
+ end
18
+
19
+ def index; end
20
+
21
+ def new
22
+ @form = form(MenuForm).instance
23
+ end
24
+
25
+ def create
26
+ @form = form(MenuForm).from_params(params)
27
+ CreateMenuHack.call(@form, current_menu_name) do
28
+ on(:ok) do
29
+ flash[:notice] = I18n.t("menu_hacks.create.success", scope: "decidim.decidim_awesome.admin")
30
+ redirect_to decidim_admin_decidim_awesome.menu_hacks_path
31
+ end
32
+
33
+ on(:invalid) do |message|
34
+ flash.now[:alert] = I18n.t("menu_hacks.create.error", error: message, scope: "decidim.decidim_awesome.admin")
35
+ render :new
36
+ end
37
+ end
38
+ end
39
+
40
+ def edit
41
+ @form = form(MenuForm).from_model(menu_item)
42
+ end
43
+
44
+ def update
45
+ @form = form(MenuForm).from_params(params)
46
+ UpdateMenuHack.call(@form, current_menu_name) do
47
+ on(:ok) do
48
+ flash[:notice] = I18n.t("menu_hacks.update.success", scope: "decidim.decidim_awesome.admin")
49
+ redirect_to decidim_admin_decidim_awesome.menu_hacks_path
50
+ end
51
+
52
+ on(:invalid) do |message|
53
+ flash.now[:alert] = I18n.t("menu_hacks.update.error", error: message, scope: "decidim.decidim_awesome.admin")
54
+ render :edit
55
+ end
56
+ end
57
+ end
58
+
59
+ def destroy
60
+ DestroyMenuHack.call(menu_item, current_menu_name, current_organization) do
61
+ on(:ok) do
62
+ flash[:notice] = I18n.t("menu_hacks.destroy.success", scope: "decidim.decidim_awesome.admin")
63
+ end
64
+ on(:invalid) do |error|
65
+ flash[:alert] = I18n.t("menu_hacks.destroy.error", scope: "decidim.decidim_awesome.admin", error: error)
66
+ end
67
+ end
68
+ redirect_to decidim_admin_decidim_awesome.menu_hacks_path
69
+ end
70
+
71
+ private
72
+
73
+ def menu_item
74
+ item = current_items.find { |i| md5(i.url) == params[:id] }
75
+ raise ActiveRecord::RecordNotFound unless item
76
+
77
+ OpenStruct.new(
78
+ raw_label: item.try(:raw_label) || { current_organization.default_locale => item.label },
79
+ url: item.url,
80
+ position: item.position,
81
+ target: item.try(:target),
82
+ visibility: item.try(:visibility),
83
+ native?: !item.respond_to?(:overrided?)
84
+ )
85
+ end
86
+
87
+ def current_items
88
+ @current_items ||= current_menu.items(true)
89
+ end
90
+
91
+ def current_menu
92
+ @current_menu ||= MenuHacker.new(current_menu_name, self)
93
+ end
94
+
95
+ def current_menu_name
96
+ :menu
97
+ end
98
+
99
+ def md5(text)
100
+ Digest::MD5.hexdigest(text)
101
+ end
102
+
103
+ def visibility_options
104
+ MenuForm::VISIBILITY_STATES.map { |key| [I18n.t(".menu_hacks.form.visibility.#{key}", scope: "decidim.decidim_awesome.admin"), key] }.to_h
105
+ end
106
+
107
+ def target_options
108
+ {
109
+ I18n.t(".menu_hacks.form.target.self", scope: "decidim.decidim_awesome.admin") => "",
110
+ I18n.t(".menu_hacks.form.target.blank", scope: "decidim.decidim_awesome.admin") => "_blank"
111
+ }
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end