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.
- checksums.yaml +7 -0
- data/LICENSE-AGPLv3.txt +661 -0
- data/README.md +180 -0
- data/Rakefile +48 -0
- data/app/assets/config/translation_sets_admin_manifest.js +2 -0
- data/app/assets/javascripts/decidim/term_customizer/admin/constraint_fields.js.es6 +45 -0
- data/app/assets/javascripts/decidim/term_customizer/admin/multifield/component.js.es6 +103 -0
- data/app/assets/javascripts/decidim/term_customizer/admin/multifield.js.es6 +5 -0
- data/app/assets/javascripts/decidim/term_customizer/admin/translation_sets_admin.js.es6 +19 -0
- data/app/assets/javascripts/decidim/term_customizer/admin/translations_admin.js.es6 +72 -0
- data/app/commands/decidim/term_customizer/admin/create_translation.rb +53 -0
- data/app/commands/decidim/term_customizer/admin/create_translation_set.rb +68 -0
- data/app/commands/decidim/term_customizer/admin/import_translation_keys.rb +59 -0
- data/app/commands/decidim/term_customizer/admin/update_translation.rb +65 -0
- data/app/commands/decidim/term_customizer/admin/update_translation_set.rb +61 -0
- data/app/controllers/decidim/term_customizer/admin/add_translations_controller.rb +72 -0
- data/app/controllers/decidim/term_customizer/admin/application_controller.rb +15 -0
- data/app/controllers/decidim/term_customizer/admin/translation_sets_controller.rb +107 -0
- data/app/controllers/decidim/term_customizer/admin/translations_controller.rb +102 -0
- data/app/forms/decidim/term_customizer/admin/translation_form.rb +39 -0
- data/app/forms/decidim/term_customizer/admin/translation_key_import_form.rb +15 -0
- data/app/forms/decidim/term_customizer/admin/translation_set_constraint_form.rb +58 -0
- data/app/forms/decidim/term_customizer/admin/translation_set_form.rb +18 -0
- data/app/forms/decidim/term_customizer/admin/translation_set_subject_component_form.rb +12 -0
- data/app/forms/decidim/term_customizer/admin/translation_set_subject_form.rb +61 -0
- data/app/helpers/decidim/term_customizer/admin/application_helper.rb +13 -0
- data/app/models/decidim/term_customizer/application_record.rb +10 -0
- data/app/models/decidim/term_customizer/constraint.rb +36 -0
- data/app/models/decidim/term_customizer/translation.rb +23 -0
- data/app/models/decidim/term_customizer/translation_set.rb +19 -0
- data/app/permissions/decidim/term_customizer/admin/permissions.rb +66 -0
- data/app/queries/decidim/term_customizer/organization_translation_sets.rb +37 -0
- data/app/queries/decidim/term_customizer/set_translations.rb +21 -0
- data/app/views/decidim/term_customizer/admin/add_translations/index.html.erb +59 -0
- data/app/views/decidim/term_customizer/admin/translation_sets/_constraint_fields.html.erb +58 -0
- data/app/views/decidim/term_customizer/admin/translation_sets/_form.html.erb +29 -0
- data/app/views/decidim/term_customizer/admin/translation_sets/edit.html.erb +9 -0
- data/app/views/decidim/term_customizer/admin/translation_sets/index.html.erb +44 -0
- data/app/views/decidim/term_customizer/admin/translation_sets/new.html.erb +9 -0
- data/app/views/decidim/term_customizer/admin/translations/_form.html.erb +15 -0
- data/app/views/decidim/term_customizer/admin/translations/edit.html.erb +7 -0
- data/app/views/decidim/term_customizer/admin/translations/index.html.erb +52 -0
- data/app/views/decidim/term_customizer/admin/translations/new.html.erb +7 -0
- data/config/locales/en.yml +65 -0
- data/config/locales/fi.yml +65 -0
- data/config/locales/sv.yml +65 -0
- data/lib/decidim/term_customizer/admin.rb +10 -0
- data/lib/decidim/term_customizer/admin_engine.rb +46 -0
- data/lib/decidim/term_customizer/engine.rb +35 -0
- data/lib/decidim/term_customizer/i18n_backend.rb +82 -0
- data/lib/decidim/term_customizer/resolver.rb +108 -0
- data/lib/decidim/term_customizer/test/factories.rb +43 -0
- data/lib/decidim/term_customizer/translation_directory.rb +50 -0
- data/lib/decidim/term_customizer/translation_store.rb +67 -0
- data/lib/decidim/term_customizer/version.rb +8 -0
- data/lib/decidim/term_customizer.rb +21 -0
- metadata +170 -0
| @@ -0,0 +1,102 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Decidim
         | 
| 4 | 
            +
              module TermCustomizer
         | 
| 5 | 
            +
                module Admin
         | 
| 6 | 
            +
                  class TranslationsController < TermCustomizer::Admin::ApplicationController
         | 
| 7 | 
            +
                    helper_method :collection, :set, :translations, :translation
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    def index
         | 
| 10 | 
            +
                      enforce_permission_to :read, :translation
         | 
| 11 | 
            +
                      @translations = collection
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    def new
         | 
| 15 | 
            +
                      enforce_permission_to :create, :translation
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                      @form = form(TranslationForm).from_model(Translation.new)
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def create
         | 
| 21 | 
            +
                      enforce_permission_to :create, :translation
         | 
| 22 | 
            +
                      @form = form(TranslationForm).from_params(
         | 
| 23 | 
            +
                        params,
         | 
| 24 | 
            +
                        current_organization: current_organization,
         | 
| 25 | 
            +
                        translation_set: set
         | 
| 26 | 
            +
                      )
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                      CreateTranslation.call(@form) do
         | 
| 29 | 
            +
                        on(:ok) do
         | 
| 30 | 
            +
                          flash[:notice] = I18n.t("translations.create.success", scope: "decidim.term_customizer.admin")
         | 
| 31 | 
            +
                          redirect_to translation_set_translations_path(set)
         | 
| 32 | 
            +
                        end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                        on(:invalid) do
         | 
| 35 | 
            +
                          flash.now[:alert] = I18n.t("translations.create.error", scope: "decidim.term_customizer.admin")
         | 
| 36 | 
            +
                          render action: "new"
         | 
| 37 | 
            +
                        end
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    def edit
         | 
| 42 | 
            +
                      enforce_permission_to :update, :translation, translation: translation
         | 
| 43 | 
            +
                      @form = form(TranslationForm).from_model(translation)
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    def update
         | 
| 47 | 
            +
                      enforce_permission_to :update, :translation, translation: translation
         | 
| 48 | 
            +
                      @form = form(TranslationForm).from_params(
         | 
| 49 | 
            +
                        params,
         | 
| 50 | 
            +
                        current_organization: current_organization,
         | 
| 51 | 
            +
                        translation_set: set
         | 
| 52 | 
            +
                      )
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                      UpdateTranslation.call(@form, translation) do
         | 
| 55 | 
            +
                        on(:ok) do
         | 
| 56 | 
            +
                          flash[:notice] = I18n.t("translations.update.success", scope: "decidim.term_customizer.admin")
         | 
| 57 | 
            +
                          redirect_to translation_set_translations_path(set)
         | 
| 58 | 
            +
                        end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                        on(:invalid) do
         | 
| 61 | 
            +
                          flash.now[:alert] = I18n.t("translations.update.invalid", scope: "decidim.term_customizer.admin")
         | 
| 62 | 
            +
                          render action: "edit"
         | 
| 63 | 
            +
                        end
         | 
| 64 | 
            +
                      end
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    def destroy
         | 
| 68 | 
            +
                      enforce_permission_to :destroy, :translation, translation: translation
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                      # Destroy all locales of the translation key
         | 
| 71 | 
            +
                      Decidim::TermCustomizer::Translation.where(
         | 
| 72 | 
            +
                        translation_set: set,
         | 
| 73 | 
            +
                        key: translation.key
         | 
| 74 | 
            +
                      ).destroy_all
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                      flash[:notice] = I18n.t("translations.destroy.success", scope: "decidim.term_customizer.admin")
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                      redirect_to translation_set_translations_path(set)
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                    private
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                    def translation_set
         | 
| 84 | 
            +
                      @translation_set ||= OrganizationTranslationSets.new(
         | 
| 85 | 
            +
                        current_organization
         | 
| 86 | 
            +
                      ).query.find(params[:translation_set_id])
         | 
| 87 | 
            +
                    end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                    def translations
         | 
| 90 | 
            +
                      @translations ||= SetTranslations.new(translation_set, current_locale)
         | 
| 91 | 
            +
                    end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                    def translation
         | 
| 94 | 
            +
                      @translation ||= Decidim::TermCustomizer::Translation.find(params[:id])
         | 
| 95 | 
            +
                    end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                    alias collection translations
         | 
| 98 | 
            +
                    alias set translation_set
         | 
| 99 | 
            +
                  end
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
              end
         | 
| 102 | 
            +
            end
         | 
| @@ -0,0 +1,39 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Decidim
         | 
| 4 | 
            +
              module TermCustomizer
         | 
| 5 | 
            +
                module Admin
         | 
| 6 | 
            +
                  class TranslationForm < Decidim::Form
         | 
| 7 | 
            +
                    include TranslatableAttributes
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    mimic :translation
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    delegate :translation_set, to: :context, prefix: false, allow_nil: true
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    attribute :key, String
         | 
| 14 | 
            +
                    translatable_attribute :value, String
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    validates :key, presence: true
         | 
| 17 | 
            +
                    validates :key, format: { with: %r{\A([a-z0-9_/]+\.?)*[a-z0-9_/]+\z} }, unless: -> { key.blank? }
         | 
| 18 | 
            +
                    validates :value, translatable_presence: true
         | 
| 19 | 
            +
                    validate :key_uniqueness
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    def map_model(model)
         | 
| 22 | 
            +
                      self.value = Hash[Decidim::TermCustomizer::Translation.where(
         | 
| 23 | 
            +
                        translation_set: model.translation_set,
         | 
| 24 | 
            +
                        key: model.key
         | 
| 25 | 
            +
                      ).map do |translation|
         | 
| 26 | 
            +
                        [translation.locale, translation.value]
         | 
| 27 | 
            +
                      end]
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    def key_uniqueness
         | 
| 31 | 
            +
                      errors.add(:key, :taken) if translation_set && translation_set.translations.where(
         | 
| 32 | 
            +
                        locale: I18n.locale,
         | 
| 33 | 
            +
                        key: key
         | 
| 34 | 
            +
                      ).exists?
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
            end
         | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Decidim
         | 
| 4 | 
            +
              module TermCustomizer
         | 
| 5 | 
            +
                module Admin
         | 
| 6 | 
            +
                  class TranslationKeyImportForm < Decidim::Form
         | 
| 7 | 
            +
                    mimic :translation
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    delegate :translation_set, to: :context, prefix: false, allow_nil: true
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    attribute :keys, Array[String]
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
            end
         | 
| @@ -0,0 +1,58 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Decidim
         | 
| 4 | 
            +
              module TermCustomizer
         | 
| 5 | 
            +
                module Admin
         | 
| 6 | 
            +
                  class TranslationSetConstraintForm < Decidim::Form
         | 
| 7 | 
            +
                    mimic :constraint
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    attribute :subject_manifest, String
         | 
| 10 | 
            +
                    attribute :subject_model, Array[TermCustomizer::Admin::TranslationSetSubjectForm]
         | 
| 11 | 
            +
                    attribute :deleted, Boolean, default: false
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    def to_param
         | 
| 14 | 
            +
                      return id if id.present?
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                      "constraint-id"
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    def map_model(model)
         | 
| 20 | 
            +
                      self.subject_manifest = model.manifest_name
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                      return unless model.subject
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                      self.subject_model = [
         | 
| 25 | 
            +
                        TermCustomizer::Admin::TranslationSetSubjectForm.from_model(
         | 
| 26 | 
            +
                          model.subject
         | 
| 27 | 
            +
                        )
         | 
| 28 | 
            +
                      ]
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    def subject_type
         | 
| 32 | 
            +
                      return unless subject_form
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                      subject_form.manifest.try(:model_class_name)
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                    def subject
         | 
| 38 | 
            +
                      return component if component
         | 
| 39 | 
            +
                      return unless subject_form
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                      subject_form.subject
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    def component
         | 
| 45 | 
            +
                      return unless subject_form
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                      subject_form.component
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                    def subject_form
         | 
| 51 | 
            +
                      @subject_form ||= subject_model.find do |sm|
         | 
| 52 | 
            +
                        sm.subject_manifest == subject_manifest
         | 
| 53 | 
            +
                      end
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
            end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Decidim
         | 
| 4 | 
            +
              module TermCustomizer
         | 
| 5 | 
            +
                module Admin
         | 
| 6 | 
            +
                  class TranslationSetForm < Decidim::Form
         | 
| 7 | 
            +
                    include TranslatableAttributes
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    mimic :translation_set
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    translatable_attribute :name, String
         | 
| 12 | 
            +
                    attribute :constraints, Array[TermCustomizer::Admin::TranslationSetConstraintForm]
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    validates :name, translatable_presence: true
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,61 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Decidim
         | 
| 4 | 
            +
              module TermCustomizer
         | 
| 5 | 
            +
                module Admin
         | 
| 6 | 
            +
                  class TranslationSetSubjectForm < Decidim::Form
         | 
| 7 | 
            +
                    attribute :subject_manifest, String
         | 
| 8 | 
            +
                    attribute :subject_id, Integer
         | 
| 9 | 
            +
                    attribute :component_model, Array[TermCustomizer::Admin::TranslationSetSubjectComponentForm]
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def map_model(model)
         | 
| 12 | 
            +
                      component = model if model.is_a?(Decidim::Component)
         | 
| 13 | 
            +
                      subject = if component
         | 
| 14 | 
            +
                                  model.participatory_space
         | 
| 15 | 
            +
                                else
         | 
| 16 | 
            +
                                  model
         | 
| 17 | 
            +
                                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                      self.subject_manifest = Decidim.participatory_space_manifests.find do |m|
         | 
| 20 | 
            +
                        m.model_class_name == subject.class.name
         | 
| 21 | 
            +
                      end.try(:name)
         | 
| 22 | 
            +
                      self.subject_id = subject.id
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                      return unless component
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                      self.component_model = [
         | 
| 27 | 
            +
                        TermCustomizer::Admin::TranslationSetSubjectComponentForm.from_params(
         | 
| 28 | 
            +
                          subject_id: subject.id,
         | 
| 29 | 
            +
                          component_id: component.id
         | 
| 30 | 
            +
                        )
         | 
| 31 | 
            +
                      ]
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    def subject
         | 
| 35 | 
            +
                      return unless manifest
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                      @subject ||= manifest.model_class_name.constantize.find_by(id: subject_id)
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    def component
         | 
| 41 | 
            +
                      return unless component_form
         | 
| 42 | 
            +
                      return unless subject
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                      subject.components.find_by(id: component_form.component_id)
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    def manifest
         | 
| 48 | 
            +
                      @manifest ||= Decidim.participatory_space_manifests.find do |m|
         | 
| 49 | 
            +
                        m.name == subject_manifest.to_sym
         | 
| 50 | 
            +
                      end
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    def component_form
         | 
| 54 | 
            +
                      @component_form ||= component_model.find do |cm|
         | 
| 55 | 
            +
                        cm.subject_id == subject_id
         | 
| 56 | 
            +
                      end
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
            end
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Decidim
         | 
| 4 | 
            +
              module TermCustomizer
         | 
| 5 | 
            +
                class Constraint < TermCustomizer::ApplicationRecord
         | 
| 6 | 
            +
                  self.table_name = "decidim_term_customizer_constraints"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  belongs_to :organization, foreign_key: :decidim_organization_id, class_name: "Decidim::Organization"
         | 
| 9 | 
            +
                  belongs_to :translation_set, class_name: "Decidim::TermCustomizer::TranslationSet", foreign_key: "translation_set_id"
         | 
| 10 | 
            +
                  belongs_to :subject, optional: true, polymorphic: true
         | 
| 11 | 
            +
                  has_many :translations, through: :translation_set
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def component
         | 
| 14 | 
            +
                    subject if subject.is_a?(Decidim::Component)
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def space
         | 
| 18 | 
            +
                    return component.participatory_space if component
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    subject
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  def manifest
         | 
| 24 | 
            +
                    space_class = space ? space.class.name : subject_type
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    Decidim.participatory_space_manifests.find do |manifest|
         | 
| 27 | 
            +
                      manifest.model_class_name == space_class
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  def manifest_name
         | 
| 32 | 
            +
                    manifest.try(:name)
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Decidim
         | 
| 4 | 
            +
              module TermCustomizer
         | 
| 5 | 
            +
                class Translation < TermCustomizer::ApplicationRecord
         | 
| 6 | 
            +
                  self.table_name = "decidim_term_customizer_translations"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  belongs_to :translation_set, class_name: "Decidim::TermCustomizer::TranslationSet", foreign_key: "translation_set_id"
         | 
| 9 | 
            +
                  has_many :constraints, through: :translation_set
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  validates :locale, presence: true
         | 
| 12 | 
            +
                  validates :key, presence: true
         | 
| 13 | 
            +
                  validates :key, format: { with: %r{\A([a-z0-9_/]+\.?)*[a-z0-9_/]+\z} }, unless: -> { key.blank? }
         | 
| 14 | 
            +
                  validates :key, uniqueness: { scope: [:translation_set, :locale] }, unless: -> { key.blank? }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  class << self
         | 
| 17 | 
            +
                    def available_locales
         | 
| 18 | 
            +
                      Translation.select("DISTINCT locale").to_a.map { |t| t.locale.to_sym }
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Decidim
         | 
| 4 | 
            +
              module TermCustomizer
         | 
| 5 | 
            +
                class TranslationSet < TermCustomizer::ApplicationRecord
         | 
| 6 | 
            +
                  self.table_name = "decidim_term_customizer_translation_sets"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  has_many :translations,
         | 
| 9 | 
            +
                           class_name: "Decidim::TermCustomizer::Translation",
         | 
| 10 | 
            +
                           foreign_key: :translation_set_id,
         | 
| 11 | 
            +
                           dependent: :destroy
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  has_many :constraints,
         | 
| 14 | 
            +
                           class_name: "Decidim::TermCustomizer::Constraint",
         | 
| 15 | 
            +
                           foreign_key: :translation_set_id,
         | 
| 16 | 
            +
                           dependent: :destroy
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| @@ -0,0 +1,66 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Decidim
         | 
| 4 | 
            +
              module TermCustomizer
         | 
| 5 | 
            +
                module Admin
         | 
| 6 | 
            +
                  class Permissions < Decidim::DefaultPermissions
         | 
| 7 | 
            +
                    def permissions
         | 
| 8 | 
            +
                      return permission_action unless user
         | 
| 9 | 
            +
                      return permission_action unless permission_action.scope == :admin
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                      unless user.admin?
         | 
| 12 | 
            +
                        disallow!
         | 
| 13 | 
            +
                        return permission_action
         | 
| 14 | 
            +
                      end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                      if read_admin_dashboard_action?
         | 
| 17 | 
            +
                        allow!
         | 
| 18 | 
            +
                        return permission_action
         | 
| 19 | 
            +
                      end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                      allowed_translation_set_action?
         | 
| 22 | 
            +
                      allowed_translation_action?
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                      permission_action
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    private
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    def translation_set
         | 
| 30 | 
            +
                      @translation_set ||= context.fetch(:translation_set, nil)
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    def translation
         | 
| 34 | 
            +
                      @translation ||= context.fetch(:translation, nil)
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                    def allowed_translation_set_action?
         | 
| 38 | 
            +
                      return unless permission_action.subject == :translation_set
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                      case permission_action.action
         | 
| 41 | 
            +
                      when :create, :read
         | 
| 42 | 
            +
                        allow!
         | 
| 43 | 
            +
                      when :update, :destroy
         | 
| 44 | 
            +
                        toggle_allow(translation_set.present?)
         | 
| 45 | 
            +
                      end
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    def allowed_translation_action?
         | 
| 49 | 
            +
                      return unless permission_action.subject == :translation
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                      case permission_action.action
         | 
| 52 | 
            +
                      when :create, :read
         | 
| 53 | 
            +
                        allow!
         | 
| 54 | 
            +
                      when :update, :destroy
         | 
| 55 | 
            +
                        toggle_allow(translation.present?)
         | 
| 56 | 
            +
                      end
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    def read_admin_dashboard_action?
         | 
| 60 | 
            +
                      permission_action.action == :read &&
         | 
| 61 | 
            +
                        permission_action.subject == :admin_dashboard
         | 
| 62 | 
            +
                    end
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
            end
         |