decidim-term_customizer 0.16.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 (57) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-AGPLv3.txt +661 -0
  3. data/README.md +180 -0
  4. data/Rakefile +48 -0
  5. data/app/assets/config/translation_sets_admin_manifest.js +2 -0
  6. data/app/assets/javascripts/decidim/term_customizer/admin/constraint_fields.js.es6 +45 -0
  7. data/app/assets/javascripts/decidim/term_customizer/admin/multifield/component.js.es6 +103 -0
  8. data/app/assets/javascripts/decidim/term_customizer/admin/multifield.js.es6 +5 -0
  9. data/app/assets/javascripts/decidim/term_customizer/admin/translation_sets_admin.js.es6 +19 -0
  10. data/app/assets/javascripts/decidim/term_customizer/admin/translations_admin.js.es6 +72 -0
  11. data/app/commands/decidim/term_customizer/admin/create_translation.rb +53 -0
  12. data/app/commands/decidim/term_customizer/admin/create_translation_set.rb +68 -0
  13. data/app/commands/decidim/term_customizer/admin/import_translation_keys.rb +59 -0
  14. data/app/commands/decidim/term_customizer/admin/update_translation.rb +65 -0
  15. data/app/commands/decidim/term_customizer/admin/update_translation_set.rb +61 -0
  16. data/app/controllers/decidim/term_customizer/admin/add_translations_controller.rb +72 -0
  17. data/app/controllers/decidim/term_customizer/admin/application_controller.rb +15 -0
  18. data/app/controllers/decidim/term_customizer/admin/translation_sets_controller.rb +107 -0
  19. data/app/controllers/decidim/term_customizer/admin/translations_controller.rb +102 -0
  20. data/app/forms/decidim/term_customizer/admin/translation_form.rb +39 -0
  21. data/app/forms/decidim/term_customizer/admin/translation_key_import_form.rb +15 -0
  22. data/app/forms/decidim/term_customizer/admin/translation_set_constraint_form.rb +58 -0
  23. data/app/forms/decidim/term_customizer/admin/translation_set_form.rb +18 -0
  24. data/app/forms/decidim/term_customizer/admin/translation_set_subject_component_form.rb +12 -0
  25. data/app/forms/decidim/term_customizer/admin/translation_set_subject_form.rb +61 -0
  26. data/app/helpers/decidim/term_customizer/admin/application_helper.rb +13 -0
  27. data/app/models/decidim/term_customizer/application_record.rb +10 -0
  28. data/app/models/decidim/term_customizer/constraint.rb +36 -0
  29. data/app/models/decidim/term_customizer/translation.rb +23 -0
  30. data/app/models/decidim/term_customizer/translation_set.rb +19 -0
  31. data/app/permissions/decidim/term_customizer/admin/permissions.rb +66 -0
  32. data/app/queries/decidim/term_customizer/organization_translation_sets.rb +37 -0
  33. data/app/queries/decidim/term_customizer/set_translations.rb +21 -0
  34. data/app/views/decidim/term_customizer/admin/add_translations/index.html.erb +59 -0
  35. data/app/views/decidim/term_customizer/admin/translation_sets/_constraint_fields.html.erb +58 -0
  36. data/app/views/decidim/term_customizer/admin/translation_sets/_form.html.erb +29 -0
  37. data/app/views/decidim/term_customizer/admin/translation_sets/edit.html.erb +9 -0
  38. data/app/views/decidim/term_customizer/admin/translation_sets/index.html.erb +44 -0
  39. data/app/views/decidim/term_customizer/admin/translation_sets/new.html.erb +9 -0
  40. data/app/views/decidim/term_customizer/admin/translations/_form.html.erb +15 -0
  41. data/app/views/decidim/term_customizer/admin/translations/edit.html.erb +7 -0
  42. data/app/views/decidim/term_customizer/admin/translations/index.html.erb +52 -0
  43. data/app/views/decidim/term_customizer/admin/translations/new.html.erb +7 -0
  44. data/config/locales/en.yml +65 -0
  45. data/config/locales/fi.yml +65 -0
  46. data/config/locales/sv.yml +65 -0
  47. data/lib/decidim/term_customizer/admin.rb +10 -0
  48. data/lib/decidim/term_customizer/admin_engine.rb +46 -0
  49. data/lib/decidim/term_customizer/engine.rb +35 -0
  50. data/lib/decidim/term_customizer/i18n_backend.rb +82 -0
  51. data/lib/decidim/term_customizer/resolver.rb +108 -0
  52. data/lib/decidim/term_customizer/test/factories.rb +43 -0
  53. data/lib/decidim/term_customizer/translation_directory.rb +50 -0
  54. data/lib/decidim/term_customizer/translation_store.rb +67 -0
  55. data/lib/decidim/term_customizer/version.rb +8 -0
  56. data/lib/decidim/term_customizer.rb +21 -0
  57. metadata +170 -0
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TermCustomizer
5
+ # This query class filters all assemblies given an organization.
6
+ class OrganizationTranslationSets < Rectify::Query
7
+ def initialize(organization)
8
+ @organization = organization
9
+ end
10
+
11
+ def query
12
+ columns = [
13
+ "DISTINCT(decidim_term_customizer_translation_sets.id)",
14
+ "name",
15
+ "name->>'#{current_locale}' AS local_name"
16
+ ]
17
+
18
+ q = Decidim::TermCustomizer::TranslationSet.joins(:constraints).where(
19
+ decidim_term_customizer_constraints: {
20
+ decidim_organization_id: @organization.id
21
+ }
22
+ ).select(columns.join(","))
23
+ q.order("local_name")
24
+ end
25
+
26
+ def count
27
+ query.count(:id)
28
+ end
29
+
30
+ private
31
+
32
+ def current_locale
33
+ I18n.locale.to_s
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TermCustomizer
5
+ # This query class filters all assemblies given an organization.
6
+ class SetTranslations < Rectify::Query
7
+ def initialize(translation_set, locale = nil)
8
+ @translation_set = translation_set
9
+ @locale = locale
10
+ end
11
+
12
+ def query
13
+ q = Decidim::TermCustomizer::Translation.where(
14
+ translation_set: @translation_set
15
+ )
16
+ q = q.where(locale: @locale) if @locale
17
+ q.order(:key)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,59 @@
1
+ <div class="card" id="add-translations-search">
2
+ <div class="card-divider">
3
+ <h2 class="card-title">
4
+ <%= t "decidim.admin.titles.translations" %>
5
+
6
+ <%= link_to t("actions.back", scope: "decidim.admin"), translation_set_translations_path(set), class: "button tiny button--title" %>
7
+ </h2>
8
+ </div>
9
+ <div class="card-section">
10
+ <div class="filters row">
11
+ <div class="column medium-4">
12
+ <%= form_tag search_translation_set_add_translations_path, method: :get do %>
13
+ <div class="filters__search">
14
+ <%= search_field_tag :term, nil, label: false, id: "data_picker-autocomplete", class: "input-group-field", placeholder: t(".search") %>
15
+ </div>
16
+ <% end %>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ </div>
21
+
22
+ <%= decidim_form_for(@form, url: translation_set_add_translations_path(set), html: { class: "form translations-form add_translations translations_form_admin" }) do |f| %>
23
+ <div id="add-translations-results" class="hide">
24
+ <div class="card" id="add-translations">
25
+ <div class="card-section">
26
+ <div class="table-scroll">
27
+ <template>
28
+ <tr>
29
+ <td>{{translation_key}}</td>
30
+ <td>{{translation_term}}</td>
31
+ <td>
32
+ <input type="hidden" name="keys[]" value="{{translation_key}}">
33
+ <%= icon_link_to "circle-x", "#", t("actions.destroy", scope: "decidim.admin"), class: "remove-translation-key action-icon--remove" %>
34
+ </td>
35
+ </tr>
36
+ </template>
37
+
38
+ <table class="table-list">
39
+ <thead>
40
+ <tr>
41
+ <th><%= t("models.translations.fields.key", scope: "decidim.admin") %></th>
42
+ <th><%= t("models.translations.fields.term", scope: "decidim.admin") %></th>
43
+ <th></th>
44
+ </tr>
45
+ </thead>
46
+ <tbody>
47
+ </tbody>
48
+ </table>
49
+ </div>
50
+ </div>
51
+ </div>
52
+
53
+ <div class="button--double form-general-submit">
54
+ <%= f.submit t(".add") %>
55
+ </div>
56
+ </div>
57
+ <% end %>
58
+
59
+ <%= javascript_include_tag "decidim/term_customizer/admin/translations_admin" %>
@@ -0,0 +1,58 @@
1
+ <%
2
+ constraint = form.object
3
+
4
+ if constraint.component
5
+ selected_component = constraint.component.id
6
+ selected_space = constraint.component.participatory_space.id
7
+ else
8
+ selected_space = constraint.subject.try(:id)
9
+ end
10
+ %>
11
+
12
+ <div class="card multifield-field constraint-section" id="<%= id %>-field">
13
+ <div class="card-divider multifield-field-divider section-divider">
14
+ <h2 class="card-title">
15
+ <span>
16
+ <%== "#{t(".constraint")}" %>
17
+ </span>
18
+
19
+ <button class="button small alert hollow remove-field button--title">
20
+ <%= t(".remove") %>
21
+ </button>
22
+ </h2>
23
+ </div>
24
+
25
+ <div class="card-section">
26
+ <div class="row column">
27
+ <%= form.select :subject_manifest, subject_manifests.map { |m| [
28
+ I18n.t("activerecord.models.#{m.model_class_name.underscore}.other"),
29
+ m.name
30
+ ] }, { include_blank: true }, class: "constraint-subject-selector" %>
31
+ </div>
32
+
33
+ <% subject_manifests.each do |manifest| %>
34
+ <div class="manifest-container" data-manifest="<%= manifest.name %>">
35
+ <% models = manifest.model_class_name.constantize.where(organization: current_organization) %>
36
+
37
+ <%= fields_for "constraints[#{index}][subject_model][#{manifest.name}]" do |subject_fields| %>
38
+ <div class="row column">
39
+ <%= subject_fields.hidden_field :subject_manifest, value: manifest.name.to_s %>
40
+ <%= subject_fields.select :subject_id, models.map { |m| [translated_attribute(m.title), m.id] }, { selected: selected_space, include_blank: true }, class: "constraint-subject-model-selector" %>
41
+ </div>
42
+
43
+ <% models.each do |model| %>
44
+ <%= fields_for "constraints[#{index}][subject_model][#{manifest.name}][component_model][#{model.id}]" do |component_fields| %>
45
+ <div class="row column component-container" data-components="<%= model.id %>">
46
+ <%= component_fields.hidden_field :subject_id, value: model.id %>
47
+ <%= component_fields.select :component_id, model.components.map { |c| [translated_attribute(c.name), c.id] }, selected: selected_component, include_blank: true %>
48
+ </div>
49
+ <% end %>
50
+ <% end %>
51
+ <% end %>
52
+ </div>
53
+ <% end %>
54
+
55
+ <%= form.hidden_field :id %>
56
+ <%= form.hidden_field :deleted %>
57
+ </div>
58
+ </div>
@@ -0,0 +1,29 @@
1
+ <div class="card">
2
+ <div class="card-divider">
3
+ <h2 class="card-title"><%= t "translation_sets.form.title", scope: "decidim.term_customizer.admin" %></h2>
4
+ </div>
5
+
6
+ <div class="card-section">
7
+ <div class="row column">
8
+ <%= form.translated :text_field, :name, autofocus: true %>
9
+ </div>
10
+
11
+ <div class="multifield-fields constraints-container" data-placeholder-id="<%= blank_constraint.to_param %>">
12
+ <template>
13
+ <%= fields_for "constraints[#{blank_constraint.to_param}]", blank_constraint do |constraint_form| %>
14
+ <%= render "constraint_fields", form: constraint_form, index: blank_constraint.to_param, id: tabs_id_for_constraint(blank_constraint) %>
15
+ <% end %>
16
+ </template>
17
+
18
+ <div class="multifield-fields-list constraints-list">
19
+ <% @form.constraints.each do |constraint| %>
20
+ <%= fields_for "constraints[]", constraint do |constraint_form| %>
21
+ <%= render "constraint_fields", form: constraint_form, index: constraint.id || blank_constraint.to_param, id: tabs_id_for_constraint(constraint) %>
22
+ <% end %>
23
+ <% end %>
24
+ </div>
25
+
26
+ <button class="button small hollow add-field add-constraint"><%= t(".add_constraint") %></button>
27
+ </div>
28
+ </div>
29
+ </div>
@@ -0,0 +1,9 @@
1
+ <%= decidim_form_for(@form, html: { class: "form translation-sets-form edit_translation_set translation_set_form_admin" }) do |f| %>
2
+ <%= render partial: "form", object: f, locals: { title: t(".title") } %>
3
+
4
+ <div class="button--double form-general-submit">
5
+ <%= f.submit t(".save") %>
6
+ </div>
7
+ <% end %>
8
+
9
+ <%= javascript_include_tag "decidim/term_customizer/admin/translation_sets_admin" %>
@@ -0,0 +1,44 @@
1
+ <div class="card" id="translation_sets">
2
+ <div class="card-divider">
3
+ <h2 class="card-title">
4
+ <%= t "decidim.admin.titles.translation_sets" %>
5
+ <% if allowed_to? :create, :translation_set %>
6
+ <%= link_to t("actions.new_translation_set", scope: "decidim.admin"), new_translation_set_path, class: "button tiny button--title" %>
7
+ <% end %>
8
+ </h2>
9
+ </div>
10
+ <div class="card-section">
11
+ <div class="table-scroll">
12
+ <table class="table-list">
13
+ <thead>
14
+ <tr>
15
+ <th><%= t("models.translation_sets.fields.name", scope: "decidim.admin") %></th>
16
+ <th></th>
17
+ </tr>
18
+ </thead>
19
+ <tbody>
20
+ <% @sets.each do |set| %>
21
+ <tr>
22
+ <td>
23
+ <% if allowed_to? :read, :translation %>
24
+ <%= link_to translated_attribute(set.name), translation_set_translations_path(set) %><br />
25
+ <% else %>
26
+ <%= translated_attribute(set.name) %>
27
+ <% end %>
28
+ </td>
29
+ <td class="table-list__actions">
30
+ <% if allowed_to? :update, :translation_set, translation_set: set %>
31
+ <%= icon_link_to "pencil", edit_translation_set_path(set), t("actions.configure", scope: "decidim.admin"), class: "action-icon--new" %>
32
+ <% end %>
33
+
34
+ <% if allowed_to? :destroy, :translation_set, translation_set: set %>
35
+ <%= 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") } %>
36
+ <% end %>
37
+ </td>
38
+ </tr>
39
+ <% end %>
40
+ </tbody>
41
+ </table>
42
+ </div>
43
+ </div>
44
+ </div>
@@ -0,0 +1,9 @@
1
+ <%= decidim_form_for(@form, html: { class: "form translation-sets-form new_translation_set translation_set_form_admin" }) do |f| %>
2
+ <%= render partial: "form", object: f, locals: { title: t(".title") } %>
3
+
4
+ <div class="button--double form-general-submit">
5
+ <%= f.submit t(".create") %>
6
+ </div>
7
+ <% end %>
8
+
9
+ <%= javascript_include_tag "decidim/term_customizer/admin/translation_sets_admin" %>
@@ -0,0 +1,15 @@
1
+ <div class="card">
2
+ <div class="card-divider">
3
+ <h2 class="card-title"><%= t "translations.form.title", scope: "decidim.term_customizer.admin" %></h2>
4
+ </div>
5
+
6
+ <div class="card-section">
7
+ <div class="row column">
8
+ <%= form.text_field :key, autofocus: true %>
9
+ </div>
10
+
11
+ <div class="row column">
12
+ <%= form.translated :text_area, :value, rows: 4 %>
13
+ </div>
14
+ </div>
15
+ </div>
@@ -0,0 +1,7 @@
1
+ <%= decidim_form_for(@form, url: translation_set_translation_path(set, translation), html: { class: "form translation-sets-form edit_translation translation_form_admin" }) do |f| %>
2
+ <%= render partial: "form", object: f, locals: { title: t(".title") } %>
3
+
4
+ <div class="button--double form-general-submit">
5
+ <%= f.submit t(".save") %>
6
+ </div>
7
+ <% end %>
@@ -0,0 +1,52 @@
1
+ <div class="card" id="translations">
2
+ <div class="card-divider">
3
+ <h2 class="card-title flex--sbc">
4
+ <div>
5
+ <%= t "decidim.admin.titles.translations" %>
6
+ </div>
7
+
8
+ <div class="flex--cc flex-gap--1">
9
+ <div id="js-other-actions-wrapper">
10
+ <% if allowed_to? :create, :translation %>
11
+ <%= link_to t("actions.add_multiple_translations", scope: "decidim.admin"), translation_set_add_translations_path(set), class: "button tiny button--simple" %>
12
+ <%= link_to t("actions.new_translation", scope: "decidim.admin"), new_translation_set_translation_path(set), class: "button tiny button--simple" %>
13
+ <% end %>
14
+ </div>
15
+ </div>
16
+ </h2>
17
+ </div>
18
+ <div class="card-section">
19
+ <div class="table-scroll">
20
+ <table class="table-list">
21
+ <thead>
22
+ <tr>
23
+ <th><%= t("models.translations.fields.key", scope: "decidim.admin") %></th>
24
+ <th><%= t("models.translations.fields.term", scope: "decidim.admin") %></th>
25
+ <th></th>
26
+ </tr>
27
+ </thead>
28
+ <tbody>
29
+ <% @translations.each do |translation| %>
30
+ <tr>
31
+ <td>
32
+ <%= translation.key %>
33
+ </td>
34
+ <td>
35
+ <%= translation.value %>
36
+ </td>
37
+ <td class="table-list__actions">
38
+ <% if allowed_to? :update, :translation, translation: translation %>
39
+ <%= icon_link_to "pencil", edit_translation_set_translation_path(set, translation), t("actions.configure", scope: "decidim.admin"), class: "action-icon--new" %>
40
+ <% end %>
41
+
42
+ <% if allowed_to? :destroy, :translation, translation: translation %>
43
+ <%= icon_link_to "circle-x", translation_set_translation_path(set, translation), t("actions.destroy", scope: "decidim.admin"), method: :delete, class: "action-icon--remove", data: { confirm: t("actions.confirm_destroy", scope: "decidim.admin") } %>
44
+ <% end %>
45
+ </td>
46
+ </tr>
47
+ <% end %>
48
+ </tbody>
49
+ </table>
50
+ </div>
51
+ </div>
52
+ </div>
@@ -0,0 +1,7 @@
1
+ <%= decidim_form_for(@form, url: translation_set_translations_path(set), html: { class: "form translation-sets-form new_translation translation_form_admin" }) do |f| %>
2
+ <%= render partial: "form", object: f, locals: { title: t(".title") } %>
3
+
4
+ <div class="button--double form-general-submit">
5
+ <%= f.submit t(".create") %>
6
+ </div>
7
+ <% end %>
@@ -0,0 +1,65 @@
1
+ en:
2
+ decidim:
3
+ admin:
4
+ actions:
5
+ add_multiple_translations: Add multiple
6
+ back: Back
7
+ new_translation_set: New translation set
8
+ new_translation: New translation
9
+ models:
10
+ translation_sets:
11
+ fields:
12
+ name: Name
13
+ translations:
14
+ fields:
15
+ key: Key
16
+ term: Term
17
+ titles:
18
+ translation_sets: Translation sets
19
+ translations: Translations
20
+ term_customizer:
21
+ admin:
22
+ add_translations:
23
+ index:
24
+ add: Add
25
+ search: Search
26
+ translation_sets:
27
+ constraint_fields:
28
+ constraint: Constraint
29
+ remove: Remove
30
+ create:
31
+ success: Translation set successfully created.
32
+ error: Error creating translation set.
33
+ destroy:
34
+ success: Translation set successfully deleted.
35
+ edit:
36
+ title: Translation set
37
+ save: Save
38
+ form:
39
+ add_constraint: Add constraint
40
+ title: Translation set
41
+ new:
42
+ create: Create
43
+ title: Translation sets
44
+ update:
45
+ success: Translation set successfully updated.
46
+ error: Error updating translation set.
47
+ translations:
48
+ create:
49
+ success: Translation successfully created.
50
+ error: Error creating translation.
51
+ destroy:
52
+ success: Translation successfully deleted.
53
+ edit:
54
+ title: Translation
55
+ save: Save
56
+ form:
57
+ title: Translation
58
+ new:
59
+ create: Create
60
+ title: Translations
61
+ update:
62
+ success: Translation successfully updated.
63
+ error: Error updating translation.
64
+ menu:
65
+ term_customizer: Term customizer
@@ -0,0 +1,65 @@
1
+ fi:
2
+ decidim:
3
+ admin:
4
+ actions:
5
+ add_multiple_translations: Lisätä useita
6
+ back: Takaisin
7
+ new_translation_set: Uusi käännöspaketti
8
+ new_translation: Uusi käännös
9
+ models:
10
+ translation_sets:
11
+ fields:
12
+ name: Nimi
13
+ translations:
14
+ fields:
15
+ key: Avain
16
+ term: Termi
17
+ titles:
18
+ translation_sets: Käännöspaketit
19
+ translations: Käännökset
20
+ term_customizer:
21
+ admin:
22
+ add_translations:
23
+ index:
24
+ add: Lisää
25
+ search: Hae
26
+ translation_sets:
27
+ constraint_fields:
28
+ constraint: Rajaussääntö
29
+ remove: Poista
30
+ create:
31
+ success: Käännöspaketin luonti onnistui.
32
+ error: Käännöspaketin luonti epäonnistui.
33
+ destroy:
34
+ success: Käännöspaketin poisto onnistui.
35
+ edit:
36
+ title: Käännöspaketti
37
+ save: Tallenna
38
+ form:
39
+ add_constraint: Lisää rajaussääntö
40
+ title: Käännöspaketti
41
+ new:
42
+ create: Luo
43
+ title: Käännöspaketit
44
+ update:
45
+ success: Käännöspaketin päivitys onnistui.
46
+ error: Käännöspaketin päivitys epäonnistui.
47
+ translations:
48
+ create:
49
+ success: Käännöksen luonti onnistui.
50
+ error: Käännöksen luonti epäonnistui.
51
+ destroy:
52
+ success: Käännöksen poisto onnistui.
53
+ edit:
54
+ title: Käännös
55
+ save: Tallenna
56
+ form:
57
+ title: Käännös
58
+ new:
59
+ create: Luo
60
+ title: Käännökset
61
+ update:
62
+ success: Käännöksen päivitys onnistui.
63
+ error: Käännöksen päivitys epäonnistui.
64
+ menu:
65
+ term_customizer: Termien kustomoinnit