decidim-decidim_awesome 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3eae6aea754d4ce898a8631f7d8c3b03946a11fc0cb15c5e1d373d98774aabeb
4
- data.tar.gz: 7f3107a8bfa4d3069c34cf28c7347686d38811fd7f9d6b1a18ff41e470216af2
3
+ metadata.gz: 7731085ea63b1e475bc932df6a856fb15f4895ebaec108aacac0ef51698f80bb
4
+ data.tar.gz: 633a38263369173bc782046137a3a91a6b0a0759690a39d5759f8eb6abb2bb3a
5
5
  SHA512:
6
- metadata.gz: dbbaaea663e4c9d317e7f971e0da7446577d6427245da4f17993b971c166a951e7eaeeb2d0264f01eaded4b3eb65b79c07ecec9e216cafc7e45ed6dc1fc010a4
7
- data.tar.gz: d77a435d6ebf77601d27344a744048e1eff43f599e64a330dcb9e7ea3f22e1efbbf808fb676891dd4404d334acc217a5a19fd892482631cc148992c342295893
6
+ metadata.gz: '08415d52fa955527e623c3efca7f04a1d5456cedc8cbaca918329700cc4dd963bcc5c895eccc496b67ffa04410ad36067d380d71152f545c698e9fb334c521dc'
7
+ data.tar.gz: c9d394b5f3080b25c0e7d1ba88b1d55ce668f537e2ee07c2401ebff37acfff5d6e49ece69bc6bf518d38b468e1ee430ab7c193e0b1489f1ed8395ccea4fbcb66
data/README.md CHANGED
@@ -106,14 +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
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!
112
+
113
+ ![CSS screenshot](examples/custom_styles.png)
114
+
109
115
 
110
116
  #### To be continued...
111
117
 
112
118
  Some things in the road-map:
113
119
 
114
120
  1. Improve the conversation in comments by allowing images
115
- 1. Direct export of surveys in PDF
116
- 1. Allow to create surveys where the responding user is known
121
+ 1. Allow to create non-private surveys where the responding user is known by admins
122
+ 1. Manipulate menus (reorder, change texts, add new items)
117
123
  1. Propose something! or even better send a PR!
118
124
 
119
125
  ## Installation
@@ -121,7 +127,7 @@ Some things in the road-map:
121
127
  Add this line to your application's Gemfile:
122
128
 
123
129
  ```ruby
124
- gem "decidim-decidim_awesome", "~> 0.6.2"
130
+ gem "decidim-decidim_awesome", "~> 0.6.3"
125
131
  ```
126
132
 
127
133
  And then execute:
@@ -1 +1,2 @@
1
1
  // = link decidim/decidim_awesome/admin.js
2
+ // = link decidim/decidim_awesome/admin/form_exit_warn.js
@@ -0,0 +1,30 @@
1
+ // = require_self
2
+
3
+ $(() => {
4
+ const $form = $("form.awesome-edit-config");
5
+ if ($form.length > 0) {
6
+ $form.find("input, textarea, select").on("change", () => {
7
+ $form.data("changed", true);
8
+ });
9
+
10
+ const safePath = $form.data("safe-path").split("?")[0];
11
+ $(document).on("click", "a", (event) => {
12
+ window.exitUrl = event.currentTarget.href;
13
+ });
14
+ $(document).on("submit", "form", (event) => {
15
+ window.exitUrl = event.currentTarget.action;
16
+ });
17
+
18
+ window.addEventListener("beforeunload", (event) => {
19
+ const exitUrl = window.exitUrl;
20
+ const hasChanged = $form.data("changed");
21
+ window.exitUrl = null;
22
+
23
+ if (!hasChanged || (exitUrl && exitUrl.includes(safePath))) {
24
+ return null;
25
+ }
26
+
27
+ event.returnValue = true;
28
+ });
29
+ }
30
+ });
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ module Admin
6
+ class CreateScopedStyle < Rectify::Command
7
+ # Public: Initializes the command.
8
+ #
9
+ def initialize(organization)
10
+ @organization = organization
11
+ @ident = rand(36**8).to_s(36)
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
+ styles = AwesomeConfig.find_or_initialize_by(var: :scoped_styles, organization: @organization)
22
+ styles.value = {} unless styles.value.is_a? Hash
23
+ # TODO: prevent (unlikely) colisions with exisiting values
24
+ styles.value[@ident] = ""
25
+ styles.save!
26
+
27
+ broadcast(:ok, @ident)
28
+ rescue StandardError => e
29
+ broadcast(:invalid, e.message)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DecidimAwesome
5
+ module Admin
6
+ class DestroyScopedStyle < Rectify::Command
7
+ # Public: Initializes the command.
8
+ #
9
+ # key - the key to destroy inise scoped_styles
10
+ # organization
11
+ def initialize(key, organization)
12
+ @key = key
13
+ @organization = organization
14
+ end
15
+
16
+ # Executes the command. Broadcasts these events:
17
+ #
18
+ # - :ok when everything is valid.
19
+ # - :invalid if we couldn't proceed.
20
+ #
21
+ # Returns nothing.
22
+ def call
23
+ styles = AwesomeConfig.find_by(var: :scoped_styles, organization: @organization)
24
+ return broadcast(:invalid, "Not a hash") unless styles&.value.is_a? Hash
25
+ return broadcast(:invalid, "#{key} key invalid") unless styles.value.has_key?(@key)
26
+
27
+ styles.value.except!(@key)
28
+ styles.save!
29
+ # remove constrains associated (a new config var is generated automatically, by removing it, it will trigger destroy on dependents)
30
+ constraint = AwesomeConfig.find_by(var: "scoped_style_#{@key}", organization: @organization)
31
+ constraint.destroy! if constraint.present?
32
+
33
+ broadcast(:ok, @key)
34
+ rescue StandardError => e
35
+ broadcast(:invalid, e.message)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -19,7 +19,6 @@ module Decidim
19
19
 
20
20
  def update
21
21
  @form = form(ConfigForm).from_params(params)
22
-
23
22
  UpdateConfig.call(@form) do
24
23
  on(:ok) do
25
24
  flash[:notice] = I18n.t("config.update.success", scope: "decidim.decidim_awesome.admin")
@@ -33,6 +32,34 @@ module Decidim
33
32
  end
34
33
  end
35
34
 
35
+ def new_scoped_style
36
+ CreateScopedStyle.call(current_organization) do
37
+ on(:ok) do |key|
38
+ flash[:notice] = I18n.t("config.create_scoped_style.success", key: key, scope: "decidim.decidim_awesome.admin")
39
+ end
40
+
41
+ on(:invalid) do |message|
42
+ flash[:alert] = I18n.t("config.create_scoped_style.error", error: message, scope: "decidim.decidim_awesome.admin")
43
+ end
44
+ end
45
+
46
+ redirect_to decidim_admin_decidim_awesome.config_path(:styles)
47
+ end
48
+
49
+ def destroy_scoped_style
50
+ DestroyScopedStyle.call(params[:key], current_organization) do
51
+ on(:ok) do |key|
52
+ flash[:notice] = I18n.t("config.destroy_scoped_style.success", key: key, scope: "decidim.decidim_awesome.admin")
53
+ end
54
+
55
+ on(:invalid) do |message|
56
+ flash[:alert] = I18n.t("config.destroy_scoped_style.error", error: message, scope: "decidim.decidim_awesome.admin")
57
+ end
58
+ end
59
+
60
+ redirect_to decidim_admin_decidim_awesome.config_path(:styles)
61
+ end
62
+
36
63
  private
37
64
 
38
65
  def constraints_for(key)
@@ -12,6 +12,7 @@ module Decidim
12
12
  attribute :use_markdown_editor, Boolean
13
13
  attribute :allow_images_in_markdown_editor, Boolean
14
14
  attribute :auto_save_forms, Boolean
15
+ attribute :scoped_styles, Hash
15
16
  attribute :intergram_for_admins, Boolean
16
17
  attribute :intergram_for_admins_settings, IntergramForm
17
18
  attribute :intergram_for_public, Boolean
@@ -0,0 +1,28 @@
1
+ <div class="row column decidim_awesome-form">
2
+ <% if config_enabled? :scoped_styles %>
3
+ <p class="help-text"><%= t("help.scoped_styles", scope: "decidim.decidim_awesome.admin.config.form") %></p>
4
+ <p class="help-text">
5
+ <%= t("help.scoped_styles_variables", scope: "decidim.decidim_awesome.admin.config.form") %><br>
6
+ <% [:primary, :secondary, :success, :warning, :alert, :highlight, :highlight_alternative].each do |color| %>
7
+ var(--<%= color %>),
8
+ <% end %>
9
+ </p>
10
+
11
+ <% form.object.scoped_styles&.each do |key, value| %>
12
+ <div class="scoped-style" data-key="<%= key %>">
13
+ <%= label_tag :scoped_styles do %>
14
+ <%= t("config.scoped_styles", scope: "activemodel.attributes", id: key) %>
15
+ <%= link_to t(".remove"), decidim_admin_decidim_awesome.destroy_scoped_style_path(key: key), method: :post, class: "float-right", data: { confirm: t(".sure_to_remove") } %>
16
+ <% end %>
17
+ <%= text_area_tag key, value, name: "config[scoped_styles][#{key}]", rows: 5 %>
18
+ <%= render(partial: "decidim/decidim_awesome/admin/config/constraints", locals: { key: "scoped_style_#{key}", constraints: constraints_for("scoped_style_#{key}") }) %>
19
+ </div>
20
+ <% end %>
21
+
22
+ <%= link_to t(".new"), decidim_admin_decidim_awesome.new_scoped_style_path, method: :post %>
23
+
24
+ <% end %>
25
+ </div>
26
+
27
+
28
+ <%= javascript_include_tag "decidim/decidim_awesome/admin/form_exit_warn" %>
@@ -1,4 +1,4 @@
1
- <%= decidim_form_for(@form, method: :patch, url: decidim_admin_decidim_awesome.config_path(params[:var])) do |f| %>
1
+ <%= decidim_form_for(@form, method: :patch, url: decidim_admin_decidim_awesome.config_path(params[:var]), html: { class: "awesome-edit-config" }, data: { "safe-path" => decidim_admin_decidim_awesome.config_path(params[:var]) }) do |f| %>
2
2
  <div class="card">
3
3
  <div class="card-divider">
4
4
  <h2 class="card-title"><%= t(".title", setting: params[:var]) %></h2>
@@ -16,6 +16,11 @@
16
16
  <%= aria_selected_link_to I18n.t("menu.surveys", scope: "decidim.decidim_awesome.admin"), decidim_admin_decidim_awesome.config_path(:surveys) %>
17
17
  </li>
18
18
  <% end %>
19
+ <% if config_enabled? :scoped_styles %>
20
+ <li <% if is_active_link?(decidim_admin_decidim_awesome.config_path(:styles)) %> class="is-active" <% end %>>
21
+ <%= aria_selected_link_to I18n.t("menu.styles", scope: "decidim.decidim_awesome.admin"), decidim_admin_decidim_awesome.config_path(:styles) %>
22
+ </li>
23
+ <% end %>
19
24
  <% if config_enabled? :allow_images_in_proposals %>
20
25
  <li <% if is_active_link?(decidim_admin_decidim_awesome.config_path(:proposals)) %> class="is-active" <% end %>>
21
26
  <%= aria_selected_link_to I18n.t("menu.proposals", scope: "decidim.decidim_awesome.admin"), decidim_admin_decidim_awesome.config_path(:proposals) %>
@@ -1,5 +1,5 @@
1
1
  <script>
2
- window.DecidimAwesome = <%= awesome_config.to_json.html_safe %>;
2
+ window.DecidimAwesome = <%= javascript_config_vars %>;
3
3
  window.DecidimAwesome.editor_uploader_path = "<%= decidim_decidim_awesome.editor_images_path %>";
4
4
  window.DecidimAwesome.texts = {
5
5
  "drag_and_drop_image": "<%= j t(".drag_and_drop_image") %>",
@@ -0,0 +1,3 @@
1
+ <style media="all">
2
+ <%= awesome_custom_styles %>
3
+ </style>
@@ -23,6 +23,7 @@
23
23
 
24
24
  <%= stylesheet_link_tag "decidim/decidim_awesome/application", media: "all" %>
25
25
  <%= stylesheet_link_tag(tenant_stylesheets, media: "all") if tenant_stylesheets %>
26
+ <%= render(partial: "layouts/decidim/decidim_awesome/custom_styles") if awesome_custom_styles %>
26
27
 
27
28
  <%= organization_colors %>
28
29
  <%= javascript_include_tag "decidim/confirm" %>
@@ -23,6 +23,7 @@
23
23
 
24
24
  <%= stylesheet_link_tag "decidim/decidim_awesome/application", media: "all" %>
25
25
  <%= stylesheet_link_tag(tenant_stylesheets, media: "all") if tenant_stylesheets %>
26
+ <%= render(partial: "layouts/decidim/decidim_awesome/custom_styles") if awesome_custom_styles %>
26
27
 
27
28
  <%= organization_colors %>
28
29
  <%= javascript_include_tag "decidim/confirm" %>
@@ -22,6 +22,7 @@ en:
22
22
  intergram_title_open: Opened chat title
23
23
  intergram_use_floating_button: If checked, the closed chat is always a button
24
24
  instead of a text
25
+ scoped_styles: 'Custom styles #%{id}'
25
26
  use_markdown_editor: Use a Markdown editor instead of the HTML editor
26
27
  constraint:
27
28
  component_id: or specifically in
@@ -85,6 +86,12 @@ en:
85
86
  delete: Delete
86
87
  edit: Edit
87
88
  title: 'Applicable only in these cases:'
89
+ create_scoped_style:
90
+ error: Error creating a new CSS box! %{error}
91
+ success: CSS box %{key} created successfully!
92
+ destroy_scoped_style:
93
+ error: Error removing CSS box! %{error}
94
+ success: CSS box %{key} removed successfully!
88
95
  experimental: Experimental options
89
96
  form:
90
97
  help:
@@ -110,9 +117,17 @@ en:
110
117
  intergram_config: Invite the <a href="https://web.telegram.org/#/im?p=@IntergramBot">@Intergram
111
118
  bot</a> to your group or start a chat with it directly. <a href="https://github.com/idoco/intergram#embed-intergram-in-your-website-with-these-2-simple-steps">+
112
119
  info</a>
120
+ scoped_styles: Create custom CSS that applies only in certain parts
121
+ of the public web (use the restrictions editor for that)
122
+ scoped_styles_variables: 'You can use the following CSS variables for
123
+ organization customized colors:'
113
124
  use_markdown_editor: This will substitute the Quill WYSIWYG editor,
114
125
  use a Markdown editor instead. Text will be rendered as HTML in the
115
126
  public pages (text in database will be saved as markdown text)
127
+ form_styles:
128
+ new: Add a new CSS box
129
+ remove: Remove this CSS box
130
+ sure_to_remove: Are you sure you want to destroy this CSS box?
116
131
  rich_text_editor_in_public_views: 'NOTE: "Rich text editor for participants"
117
132
  is enabled, this option won''t apply. Use the editors hacks instead to
118
133
  enable images in proposals.'
@@ -148,6 +163,7 @@ en:
148
163
  editors: Editor hacks
149
164
  livechat: Live Chat
150
165
  proposals: Proposals hacks
166
+ styles: Custom styles
151
167
  surveys: Surveys & forms
152
168
  config:
153
169
  intergram:
@@ -59,6 +59,18 @@ module Decidim
59
59
  false
60
60
  end
61
61
 
62
+ # allows admins to created specific CSS snippets affecting only some specific parts
63
+ # Valid values differ a little from the previous convention:
64
+ # :disabled => false and non available, hidden from admins
65
+ # Hash => hash of different css text, each key will be used for the contraints
66
+ # Admins create this hash dynamically but some pre-defined css boxes can be created here as:
67
+ # {
68
+ # some_identifier: ".wrapper { background: red; }"
69
+ # }
70
+ config_accessor :scoped_styles do
71
+ {}
72
+ end
73
+
62
74
  # these settings do not follow the :disabled convention but
63
75
  # depends on the previous intergram configurations
64
76
  config_accessor :intergram_url do
@@ -13,6 +13,8 @@ module Decidim
13
13
  # Add admin engine routes here
14
14
  resources :constraints
15
15
  resources :config, param: :var, only: [:show, :update]
16
+ post :new_scoped_style, to: "config#new_scoped_style"
17
+ post :destroy_scoped_style, param: :key, to: "config#destroy_scoped_style"
16
18
  get :checks, to: "checks#index"
17
19
  root to: "config#show", var: :editors
18
20
  end
@@ -19,6 +19,10 @@ module Decidim
19
19
  @awesome_config ||= awesome_config_instance.config
20
20
  end
21
21
 
22
+ def javascript_config_vars
23
+ awesome_config.except(:scoped_styles).to_json.html_safe
24
+ end
25
+
22
26
  def show_public_intergram?
23
27
  return unless awesome_config[:intergram_for_public]
24
28
  return true unless awesome_config[:intergram_for_public_settings][:require_login]
@@ -45,6 +49,18 @@ module Decidim
45
49
  return @tenant_stylesheets = current_organization.host.to_s if File.exist?("#{prefix}.css") || File.exist?("#{prefix}.scss") || File.exist?("#{prefix}.scss.erb")
46
50
  end
47
51
 
52
+ # Collects all CSS that is applied in the current URL context
53
+ def awesome_custom_styles
54
+ return unless awesome_config[:scoped_styles]
55
+ return @awesome_custom_styles if @awesome_custom_styles
56
+
57
+ styles = awesome_config[:scoped_styles]&.filter do |key, _value|
58
+ config = AwesomeConfig.find_by(var: "scoped_style_#{key}", organization: current_organization)
59
+ @awesome_config_instance.valid_in_context?(config.constraints)
60
+ end
61
+ @awesome_custom_styles = styles.values.join("\n")
62
+ end
63
+
48
64
  def version_prefix
49
65
  "v#{Decidim.version[0..3]}"
50
66
  end
@@ -79,6 +79,19 @@ module Decidim
79
79
  config[setting]
80
80
  end
81
81
 
82
+ # checks if some constraint blocks the validity fot the current context
83
+ def valid_in_context?(constraints)
84
+ # if no constraints defined, applies to everything
85
+ return true if constraints.blank?
86
+
87
+ # check if current context matches some constraint
88
+ constraints.detect do |constraint|
89
+ # if some setting is different, rejects
90
+ invalid = constraint.settings.detect { |key, val| context[key.to_sym].to_s != val.to_s }
91
+ invalid.blank?
92
+ end
93
+ end
94
+
82
95
  private
83
96
 
84
97
  def map_defaults
@@ -112,18 +125,6 @@ module Decidim
112
125
  end
113
126
  true
114
127
  end
115
-
116
- def valid_in_context?(constraints)
117
- # if no constraints defined, applies to everything
118
- return true if constraints.blank?
119
-
120
- # check if current context matches some constraint
121
- constraints.detect do |constraint|
122
- # if some setting is different, rejects
123
- invalid = constraint.settings.detect { |key, val| context[key.to_sym] != val }
124
- invalid.blank?
125
- end
126
- end
127
128
  end
128
129
  end
129
130
  end
@@ -3,7 +3,7 @@
3
3
  module Decidim
4
4
  # This holds the decidim-decidim_awesome version.
5
5
  module DecidimAwesome
6
- VERSION = "0.6.2"
6
+ VERSION = "0.6.3"
7
7
  COMPAT_DECIDIM_VERSION = [">= 0.22.0", "< 0.24"].freeze
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decidim-decidim_awesome
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Vergés
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-29 00:00:00.000000000 Z
11
+ date: 2021-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: decidim-admin
@@ -116,6 +116,7 @@ files:
116
116
  - app/assets/images/decidim/decidim_awesome/platoniq-logo.png
117
117
  - app/assets/javascripts/decidim/decidim_awesome/admin.js
118
118
  - app/assets/javascripts/decidim/decidim_awesome/admin/constraints.js.es6
119
+ - app/assets/javascripts/decidim/decidim_awesome/admin/form_exit_warn.js.es6
119
120
  - app/assets/javascripts/decidim/decidim_awesome/application.js
120
121
  - app/assets/javascripts/decidim/decidim_awesome/awesome_map/api_fetcher.js.es6
121
122
  - app/assets/javascripts/decidim/decidim_awesome/awesome_map/categories.js.es6
@@ -140,7 +141,9 @@ files:
140
141
  - app/assets/stylesheets/decidim/decidim_awesome/forms/autosave.scss
141
142
  - app/awesome_overrides/presenters/decidim/proposals/proposal_presenter_override.rb
142
143
  - app/commands/decidim/decidim_awesome/admin/create_constraint.rb
144
+ - app/commands/decidim/decidim_awesome/admin/create_scoped_style.rb
143
145
  - app/commands/decidim/decidim_awesome/admin/destroy_constraint.rb
146
+ - app/commands/decidim/decidim_awesome/admin/destroy_scoped_style.rb
144
147
  - app/commands/decidim/decidim_awesome/admin/update_config.rb
145
148
  - app/commands/decidim/decidim_awesome/admin/update_constraint.rb
146
149
  - app/commands/decidim/decidim_awesome/create_editor_image.rb
@@ -172,6 +175,7 @@ files:
172
175
  - app/views/decidim/decidim_awesome/admin/config/_form_editors.html.erb
173
176
  - app/views/decidim/decidim_awesome/admin/config/_form_livechat.html.erb
174
177
  - app/views/decidim/decidim_awesome/admin/config/_form_proposals.html.erb
178
+ - app/views/decidim/decidim_awesome/admin/config/_form_styles.html.erb
175
179
  - app/views/decidim/decidim_awesome/admin/config/_form_surveys.html.erb
176
180
  - app/views/decidim/decidim_awesome/admin/config/_modal.html.erb
177
181
  - app/views/decidim/decidim_awesome/admin/config/show.html.erb
@@ -185,6 +189,7 @@ files:
185
189
  - app/views/layouts/decidim/admin/_header.html.erb
186
190
  - app/views/layouts/decidim/admin/decidim_awesome.html.erb
187
191
  - app/views/layouts/decidim/decidim_awesome/_awesome_config.html.erb
192
+ - app/views/layouts/decidim/decidim_awesome/_custom_styles.html.erb
188
193
  - app/views/layouts/decidim/decidim_awesome/_intergram_widget.html.erb
189
194
  - app/views/v0.22/layouts/decidim/_head.html.erb
190
195
  - app/views/v0.22/layouts/decidim/admin/_header.html.erb