decidim-term_customizer 0.17.0 → 0.20.0

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/Rakefile +0 -8
  3. data/app/assets/config/translation_sets_admin_manifest.js +1 -0
  4. data/app/assets/javascripts/decidim/term_customizer/admin/translation_sets_admin.js.es6 +3 -1
  5. data/app/assets/javascripts/decidim/term_customizer/admin/translations_admin.js.es6 +6 -1
  6. data/app/commands/decidim/term_customizer/admin/create_translation.rb +3 -0
  7. data/app/commands/decidim/term_customizer/admin/destroy_translations.rb +3 -0
  8. data/app/commands/decidim/term_customizer/admin/duplicate_translation_set.rb +61 -0
  9. data/app/commands/decidim/term_customizer/admin/import_set_translations.rb +3 -0
  10. data/app/commands/decidim/term_customizer/admin/import_translation_keys.rb +3 -0
  11. data/app/commands/decidim/term_customizer/admin/update_translation.rb +8 -3
  12. data/app/controllers/decidim/term_customizer/admin/add_translations_controller.rb +2 -1
  13. data/app/controllers/decidim/term_customizer/admin/translation_sets_controller.rb +29 -7
  14. data/app/controllers/decidim/term_customizer/admin/translations_controller.rb +21 -4
  15. data/app/controllers/decidim/term_customizer/admin/translations_destroys_controller.rb +4 -1
  16. data/app/forms/decidim/term_customizer/admin/translations_destroy_form.rb +3 -3
  17. data/app/views/decidim/term_customizer/admin/add_translations/index.html.erb +1 -1
  18. data/app/views/decidim/term_customizer/admin/translation_sets/_form.html.erb +2 -2
  19. data/app/views/decidim/term_customizer/admin/translation_sets/index.html.erb +8 -0
  20. data/app/views/decidim/term_customizer/admin/translations/_export_dropdown.html.erb +1 -1
  21. data/app/views/decidim/term_customizer/admin/translations/_form.html.erb +1 -1
  22. data/app/views/decidim/term_customizer/admin/translations/index.html.erb +2 -2
  23. data/app/views/decidim/term_customizer/admin/translations/new_import.html.erb +1 -1
  24. data/app/views/decidim/term_customizer/admin/translations_destroys/new.html.erb +1 -1
  25. data/config/locales/ca.yml +8 -1
  26. data/config/locales/en.yml +8 -1
  27. data/config/locales/es.yml +8 -1
  28. data/config/locales/fi.yml +8 -1
  29. data/config/locales/fr.yml +9 -2
  30. data/config/locales/sv.yml +8 -1
  31. data/lib/decidim/term_customizer.rb +17 -0
  32. data/lib/decidim/term_customizer/admin_engine.rb +2 -1
  33. data/lib/decidim/term_customizer/context.rb +11 -0
  34. data/lib/decidim/term_customizer/context/base.rb +33 -0
  35. data/lib/decidim/term_customizer/context/controller_context.rb +31 -0
  36. data/lib/decidim/term_customizer/context/job_context.rb +53 -0
  37. data/lib/decidim/term_customizer/engine.rb +10 -29
  38. data/lib/decidim/term_customizer/loader.rb +4 -3
  39. data/lib/decidim/term_customizer/plural_forms_form.rb +23 -0
  40. data/lib/decidim/term_customizer/plural_forms_manager.rb +103 -0
  41. data/lib/decidim/term_customizer/version.rb +2 -2
  42. metadata +22 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 16eec8f526df47ea82ef79a644e4afd290f64e7e1f7aa2fea64723ad7a30d6b9
4
- data.tar.gz: 93c4464c8c3e2b3437df94b25e0f457e60ad1f18240c1fbc6609421600888805
3
+ metadata.gz: 9e7c2537197c329aba4d64541635965b8a2b91e12fe8c0d8e3dac11df2f5b215
4
+ data.tar.gz: 80a01c0978ada36f8561d1f475fcd1ac07e99b0c5664c13484530672f808958e
5
5
  SHA512:
6
- metadata.gz: 4efdea5c3cca3ec8cd9f1e4d068b63f587b84f1ec9c175f9be2d1ff5832b688c467655596fcc85be7d2c2d6f22acffcf3c07913910c6a74151a4b5e4bb35aff6
7
- data.tar.gz: 8864a676c3562377cc114556c058cbe50983d4b4691f9007130de45d3addbc8bb0ab4dd670c11e2a1412e53b748f06a06b78d23f652b379808ee499be24ce99c
6
+ metadata.gz: 45293721c61381231be57197d1e616d6fa3edd2bafd5e39fe31aeea015b8b8a823b1a939a2f3118d8b9ca411c3542affcbd7323f9e75297abb52d103a115674d
7
+ data.tar.gz: 742f453412332567ae90056f19a40066fae076cb57275342451ffa4a879de9f56470435e583b00ebdcd330ff8fced30afb9fd006d8ec4ee29510ffa29355ecba
data/Rakefile CHANGED
@@ -38,11 +38,3 @@ task :development_app do
38
38
  install_module("development_app")
39
39
  seed_db("development_app")
40
40
  end
41
-
42
- # Run all tests, include all
43
- RSpec::Core::RakeTask.new(:spec) do |t|
44
- t.verbose = false
45
- end
46
-
47
- # Run both by default
48
- task default: [:spec]
@@ -1,2 +1,3 @@
1
1
  //= link decidim/term_customizer/admin/translation_sets_admin.js
2
2
  //= link decidim/term_customizer/admin/translations_admin.js
3
+ //= link decidim/term_customizer/admin/translations_admin_bulk.js
@@ -15,5 +15,7 @@ $(() => {
15
15
  }
16
16
  );
17
17
 
18
- $(".constraints-list", $fields).constraintSection();
18
+ $(".constraints-list .constraint-section", $fields).each((_i, el) => {
19
+ $(el).constraintSection();
20
+ });
19
21
  });
@@ -32,8 +32,13 @@ $(() => {
32
32
  const re = new RegExp(`(${sanitizedSearch.split(" ").join("|")})`, "gi");
33
33
  const modelId = item[0];
34
34
  const title = item[1];
35
+ // The terms are already escaped but when they are rendered to a data
36
+ // attribute, they get unescaped when those values are used. The only
37
+ // character we need to replace is the ampersand
38
+ const value = title.replace(/&/g, "&");
39
+
35
40
  const val = `${title} - ${modelId}`;
36
- return `<div class="autocomplete-suggestion" data-model-id="${modelId}" data-val="${title}">${val.replace(re, "<b>$1</b>")}</div>`;
41
+ return `<div class="autocomplete-suggestion" data-model-id="${modelId}" data-val="${value}">${val.replace(re, "<b>$1</b>")}</div>`;
37
42
  },
38
43
  onSelect: function(event, term, item) {
39
44
  const $suggestions = $search.data("sc");
@@ -6,6 +6,8 @@ module Decidim
6
6
  # A command with all the business logic when creating a new translation
7
7
  # set in the system.
8
8
  class CreateTranslation < Rectify::Command
9
+ include TermCustomizer::PluralFormsForm
10
+
9
11
  # Public: Initializes the command.
10
12
  #
11
13
  # form - A form object with the params.
@@ -24,6 +26,7 @@ module Decidim
24
26
 
25
27
  transaction do
26
28
  @translations = create_translations
29
+ create_plural_forms(@translations)
27
30
  end
28
31
 
29
32
  if @translations.length.positive?
@@ -6,6 +6,8 @@ module Decidim
6
6
  # A command with all the business logic when an admin destroys
7
7
  # translations from a translation set.
8
8
  class DestroyTranslations < Rectify::Command
9
+ include TermCustomizer::PluralFormsForm
10
+
9
11
  # Public: Initializes the command.
10
12
  #
11
13
  # form - A form object with the params.
@@ -22,6 +24,7 @@ module Decidim
22
24
  def call
23
25
  return broadcast(:invalid) unless form.valid?
24
26
 
27
+ destroy_plural_forms(form.translations)
25
28
  destroy_translations
26
29
 
27
30
  broadcast(:ok)
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TermCustomizer
5
+ module Admin
6
+ # This command is executed when the user duplicates a translation set from
7
+ # the admin panel.
8
+ class DuplicateTranslationSet < Rectify::Command
9
+ # Initializes a DuplicateTranslationSet Command.
10
+ #
11
+ # form - A form object with the params.
12
+ # set - The instance of the translation set to be duplicated.
13
+ def initialize(form, set)
14
+ @form = form
15
+ @set = set
16
+ end
17
+
18
+ # Updates the blog if valid.
19
+ #
20
+ # Broadcasts :ok if successful, :invalid otherwise.
21
+ def call
22
+ return broadcast(:invalid) if form.invalid?
23
+
24
+ transaction do
25
+ duplicate_translation_set!
26
+ end
27
+
28
+ broadcast(:ok, set)
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :form, :set
34
+
35
+ def duplicate_translation_set!
36
+ duplicated = TermCustomizer::TranslationSet.create!(name: form.name)
37
+
38
+ # Add the constraints
39
+ set.constraints.each do |c|
40
+ duplicated.constraints.create!(
41
+ organization: form.current_organization,
42
+ subject: c.subject,
43
+ subject_type: c.subject_type
44
+ )
45
+ end
46
+
47
+ # Add the translations
48
+ set.translations.each do |t|
49
+ duplicated.translations.create!(
50
+ locale: t.locale,
51
+ key: t.key,
52
+ value: t.value
53
+ )
54
+ end
55
+
56
+ duplicated
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -10,6 +10,8 @@ module Decidim
10
10
  # supported import formats or a ZIP file containing a supported import
11
11
  # file.
12
12
  class ImportSetTranslations < Rectify::Command
13
+ include TermCustomizer::PluralFormsForm
14
+
13
15
  # Public: Initializes the command.
14
16
  #
15
17
  # form - A form object with the params.
@@ -30,6 +32,7 @@ module Decidim
30
32
  return broadcast(:invalid) if form.invalid?
31
33
 
32
34
  @translations = import_translations
35
+ create_plural_forms(@translations)
33
36
 
34
37
  if @translations.length.positive?
35
38
  broadcast(:ok, @translations)
@@ -6,6 +6,8 @@ module Decidim
6
6
  # A command with all the business logic when creating new translations
7
7
  # from the keys submitted through the form.
8
8
  class ImportTranslationKeys < Rectify::Command
9
+ include TermCustomizer::PluralFormsForm
10
+
9
11
  # Public: Initializes the command.
10
12
  #
11
13
  # form - A form object with the params.
@@ -24,6 +26,7 @@ module Decidim
24
26
 
25
27
  transaction do
26
28
  @translations = create_translations
29
+ create_plural_forms(@translations)
27
30
  end
28
31
 
29
32
  if @translations.length.positive?
@@ -6,6 +6,8 @@ module Decidim
6
6
  # This command is executed when the user changes a translation from the
7
7
  # admin panel.
8
8
  class UpdateTranslation < Rectify::Command
9
+ include TermCustomizer::PluralFormsForm
10
+
9
11
  # Public: Initializes the command.
10
12
  #
11
13
  # form - A form object with the params.
@@ -25,7 +27,8 @@ module Decidim
25
27
  return broadcast(:invalid) if form.invalid?
26
28
 
27
29
  transaction do
28
- update_translations!
30
+ @translations = update_translations!
31
+ create_plural_forms(@translations)
29
32
  end
30
33
 
31
34
  broadcast(:ok, translation)
@@ -36,7 +39,7 @@ module Decidim
36
39
  attr_reader :form, :translation
37
40
 
38
41
  def update_translations!
39
- form.value.each do |locale, value|
42
+ form.value.map do |locale, value|
40
43
  l_translation = TermCustomizer::Translation.find_by(
41
44
  translation_set: translation.translation_set,
42
45
  key: translation.key,
@@ -50,13 +53,15 @@ module Decidim
50
53
  locale: locale
51
54
  )
52
55
  else
53
- TermCustomizer::Translation.create!(
56
+ l_translation = TermCustomizer::Translation.create!(
54
57
  translation_set: translation.translation_set,
55
58
  key: form.key,
56
59
  value: value,
57
60
  locale: locale
58
61
  )
59
62
  end
63
+
64
+ l_translation
60
65
  end
61
66
  end
62
67
  end
@@ -16,6 +16,7 @@ module Decidim
16
16
  enforce_permission_to :create, :translation
17
17
  @form = form(TranslationKeyImportForm).from_params(
18
18
  params,
19
+ current_organization: current_organization,
19
20
  translation_set: set
20
21
  )
21
22
 
@@ -40,7 +41,7 @@ module Decidim
40
41
  translations = directory.translations_search(params[:term])
41
42
  translations.reject! { |k| reject_keys.include?(k) }
42
43
 
43
- render json: translations.map { |k, v| [k, v] }
44
+ render json: translations.map { |k, v| [k, ERB::Util.html_escape(v)] }
44
45
  end
45
46
 
46
47
  private
@@ -60,7 +60,7 @@ module Decidim
60
60
  end
61
61
 
62
62
  on(:invalid) do
63
- flash.now[:alert] = I18n.t("translation_sets.update.invalid", scope: "decidim.term_customizer.admin")
63
+ flash.now[:alert] = I18n.t("translation_sets.update.error", scope: "decidim.term_customizer.admin")
64
64
  render action: "edit"
65
65
  end
66
66
  end
@@ -75,15 +75,37 @@ module Decidim
75
75
  redirect_to translation_sets_path
76
76
  end
77
77
 
78
- def export
79
- enforce_permission_to :export, :translation_set, translation_set: set
80
- name = "set-translations"
78
+ def duplicate
79
+ enforce_permission_to :create, :translation_set
80
+
81
+ # Automatically generate the name
82
+ name_attrs = {}.tap do |hash|
83
+ current_organization.available_locales.each do |locale|
84
+ hash["name_#{locale}"] = I18n.t(
85
+ "translation_sets.duplicate.copied_set_name",
86
+ name: set.name[locale],
87
+ locale: locale,
88
+ scope: "decidim.term_customizer.admin"
89
+ )
90
+ end
91
+ end
81
92
 
82
- ExportJob.perform_later(current_user, set, name, params[:format] || "json")
93
+ @form = form(TranslationSetForm).from_params(
94
+ params.merge(name_attrs),
95
+ current_organization: current_organization
96
+ )
83
97
 
84
- flash[:notice] = I18n.t("exports.notice", scope: "decidim.admin")
98
+ DuplicateTranslationSet.call(@form, set) do
99
+ on(:ok) do
100
+ flash[:notice] = I18n.t("translation_sets.duplicate.success", scope: "decidim.term_customizer.admin")
101
+ redirect_to translation_sets_path
102
+ end
85
103
 
86
- redirect_to translation_set_translations_path(set)
104
+ on(:invalid) do
105
+ flash.now[:alert] = I18n.t("translation_sets.duplicate.error", scope: "decidim.term_customizer.admin")
106
+ redirect_to translation_sets_path
107
+ end
108
+ end
87
109
  end
88
110
 
89
111
  private
@@ -59,7 +59,7 @@ module Decidim
59
59
  end
60
60
 
61
61
  on(:invalid) do
62
- flash.now[:alert] = I18n.t("translations.update.invalid", scope: "decidim.term_customizer.admin")
62
+ flash.now[:alert] = I18n.t("translations.update.error", scope: "decidim.term_customizer.admin")
63
63
  render action: "edit"
64
64
  end
65
65
  end
@@ -69,16 +69,30 @@ module Decidim
69
69
  enforce_permission_to :destroy, :translation, translation: translation
70
70
 
71
71
  # Destroy all locales of the translation key
72
- Decidim::TermCustomizer::Translation.where(
72
+ pfm = TermCustomizer::PluralFormsManager.new(current_organization)
73
+ translations = Decidim::TermCustomizer::Translation.where(
73
74
  translation_set: set,
74
75
  key: translation.key
75
- ).destroy_all
76
+ )
77
+ pfm.destroy!(translations)
78
+ translations.destroy_all
76
79
 
77
80
  flash[:notice] = I18n.t("translations.destroy.success", scope: "decidim.term_customizer.admin")
78
81
 
79
82
  redirect_to translation_set_translations_path(set)
80
83
  end
81
84
 
85
+ def export
86
+ enforce_permission_to :export, :translation_set, translation_set: set
87
+ name = "set-translations"
88
+
89
+ ExportJob.perform_later(current_user, set, name, params[:format] || "json")
90
+
91
+ flash[:notice] = I18n.t("exports.notice", scope: "decidim.admin")
92
+
93
+ redirect_to translation_set_translations_path(set)
94
+ end
95
+
82
96
  def new_import
83
97
  enforce_permission_to :import, :translation_set, translation_set: set
84
98
 
@@ -88,7 +102,10 @@ module Decidim
88
102
  def import
89
103
  enforce_permission_to :import, :translation_set, translation_set: set
90
104
 
91
- @import = form(Admin::TranslationsImportForm).from_params(params)
105
+ @import = form(Admin::TranslationsImportForm).from_params(
106
+ params,
107
+ current_organization: current_organization
108
+ )
92
109
  ImportSetTranslations.call(@import, set) do
93
110
  on(:ok) do
94
111
  flash[:notice] = I18n.t("translations.import.success", scope: "decidim.term_customizer.admin")
@@ -38,7 +38,10 @@ module Decidim
38
38
  def set_form
39
39
  @form = form(Admin::TranslationsDestroyForm).from_params(
40
40
  params
41
- ).with_context(translation_set: set)
41
+ ).with_context(
42
+ current_organization: current_organization,
43
+ translation_set: set
44
+ )
42
45
  end
43
46
 
44
47
  def translation_set
@@ -20,7 +20,7 @@ module Decidim
20
20
 
21
21
  @translations ||= translation_set.translations.where(
22
22
  key: translation_keys
23
- )
23
+ ).order(:id)
24
24
  end
25
25
 
26
26
  # Only the translations passed with the IDs (current locale).
@@ -28,8 +28,8 @@ module Decidim
28
28
  return [] unless translation_set
29
29
 
30
30
  @translations_current ||= translation_set.translations.where(
31
- id: translation_ids
32
- ).uniq
31
+ id: translation_ids.uniq
32
+ ).order(:id)
33
33
  end
34
34
 
35
35
  private
@@ -2,7 +2,7 @@
2
2
  <div class="card-divider">
3
3
  <h2 class="card-title flex--sbc">
4
4
  <div>
5
- <%= link_to t("decidim.term_customizer.menu.term_customizer"), root_path %>
5
+ <%= link_to t("decidim.term_customizer.menu.term_customizer"), translation_sets_path %>
6
6
  &gt;
7
7
  <%= link_to translated_attribute(set.name), translation_set_translations_path(set) %>
8
8
  &gt;
@@ -2,7 +2,7 @@
2
2
  <div class="card-divider">
3
3
  <h2 class="card-title flex--sbc">
4
4
  <div>
5
- <%= link_to t("decidim.term_customizer.menu.term_customizer"), root_path %>
5
+ <%= link_to t("decidim.term_customizer.menu.term_customizer"), translation_sets_path %>
6
6
  &gt;
7
7
  <%= t "translation_sets.form.title", scope: "decidim.term_customizer.admin" %>
8
8
 
@@ -14,7 +14,7 @@
14
14
 
15
15
  <div class="flex--cc flex-gap--1">
16
16
  <div id="js-other-actions-wrapper">
17
- <%= link_to t("actions.back", scope: "decidim.term_customizer.admin"), root_path, class: "button hollow tiny button--simple" %>
17
+ <%= link_to t("actions.back", scope: "decidim.term_customizer.admin"), translation_sets_path, class: "button hollow tiny button--simple" %>
18
18
  </div>
19
19
  </div>
20
20
  </h2>
@@ -38,10 +38,18 @@
38
38
  <% end %>
39
39
  </td>
40
40
  <td class="table-list__actions">
41
+ <% if allowed_to? :read, :translation %>
42
+ <%= icon_link_to "eye", translation_set_translations_path(set), t("actions.view", scope: "decidim.term_customizer.admin"), class: "action-icon--show" %>
43
+ <% end %>
44
+
41
45
  <% if allowed_to? :update, :translation_set, translation_set: set %>
42
46
  <%= icon_link_to "pencil", edit_translation_set_path(set), t("actions.configure", scope: "decidim.admin"), class: "action-icon--new" %>
43
47
  <% end %>
44
48
 
49
+ <% if allowed_to? :create, :translation_set %>
50
+ <%= icon_link_to "fork", duplicate_translation_set_path(set), t("actions.duplicate", scope: "decidim.term_customizer.admin"), method: :post, class: "action-icon--new", data: { confirm: t("actions.confirm_duplicate", scope: "decidim.term_customizer.admin") } %>
51
+ <% end %>
52
+
45
53
  <% if allowed_to? :destroy, :translation_set, translation_set: set %>
46
54
  <%= icon_link_to "circle-x", translation_set_path(set), t("actions.destroy", scope: "decidim.admin"), method: :delete, class: "action-icon--remove", data: { confirm: t("actions.confirm_destroy", scope: "decidim.admin") } %>
47
55
  <% end %>
@@ -2,7 +2,7 @@
2
2
  <div class="dropdown-pane" id="export-dropdown" data-dropdown data-position=bottom data-alignment=right data-auto-focus="true" data-close-on-click="true">
3
3
  <ul class="vertical menu add-components">
4
4
  <% %w{CSV JSON Excel}.each do |format| %>
5
- <li class="exports--format--<%= format.downcase %> exports--translations"><%= link_to t("decidim.admin.exports.export_as", name: t("decidim.term_customizer.admin.titles.translations"), export_format: format.upcase), export_translation_set_path(set, format: format), method: :post %></li>
5
+ <li class="exports--format--<%= format.downcase %> exports--translations"><%= link_to t("decidim.admin.exports.export_as", name: t("decidim.term_customizer.admin.titles.translations"), export_format: format.upcase), export_translation_set_translations_path(set, format: format), method: :post %></li>
6
6
  <% end %>
7
7
  </ul>
8
8
  </div>