decidim-term_customizer 0.17.0 → 0.20.0

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 (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>