diff --git a/Gemfile b/Gemfile index dc5e1a0e7..6e8cf5c24 100644 --- a/Gemfile +++ b/Gemfile @@ -49,6 +49,7 @@ gem "savon", "~> 2.12.0" gem "sitemap_generator", "~> 6.0.1" gem "social-share-button", "~> 1.1" gem "sprockets", "~> 3.7.2" +gem "translator-text", "~> 0.1.0" gem "turbolinks", "~> 2.5.3" gem "turnout", "~> 2.4.0" gem "uglifier", "~> 4.1.2" diff --git a/Gemfile.lock b/Gemfile.lock index e90a4c4a0..582f12578 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -168,6 +168,31 @@ GEM devise (>= 4.0) diff-lcs (1.3) docile (1.3.1) + dry-configurable (0.7.0) + concurrent-ruby (~> 1.0) + dry-container (0.6.0) + concurrent-ruby (~> 1.0) + dry-configurable (~> 0.1, >= 0.1.3) + dry-core (0.4.7) + concurrent-ruby (~> 1.0) + dry-equalizer (0.2.1) + dry-inflector (0.1.2) + dry-logic (0.4.2) + dry-container (~> 0.2, >= 0.2.6) + dry-core (~> 0.2) + dry-equalizer (~> 0.2) + dry-struct (0.5.1) + dry-core (~> 0.4, >= 0.4.3) + dry-equalizer (~> 0.2) + dry-types (~> 0.13) + ice_nine (~> 0.11) + dry-types (0.13.3) + concurrent-ruby (~> 1.0) + dry-container (~> 0.3) + dry-core (~> 0.4, >= 0.4.4) + dry-equalizer (~> 0.2) + dry-inflector (~> 0.1, >= 0.1.2) + dry-logic (~> 0.4, >= 0.4.2) email_spec (2.1.1) htmlentities (~> 4.3.3) launchy (~> 2.1) @@ -223,6 +248,9 @@ GEM highline (2.0.0) html_tokenizer (0.0.7) htmlentities (4.3.4) + httparty (0.17.0) + mime-types (~> 3.0) + multi_xml (>= 0.5.2) httpi (2.4.4) rack socksify @@ -237,6 +265,7 @@ GEM parser (>= 2.2.3.0) rainbow (>= 2.2.2, < 4.0) terminal-table (>= 1.5.1) + ice_nine (0.11.2) initialjs-rails (0.2.0.5) railties (>= 3.1, < 6.0) invisible_captcha (0.10.0) @@ -493,6 +522,9 @@ GEM tilt (2.0.8) tins (1.16.3) tomlrb (1.2.7) + translator-text (0.1.0) + dry-struct (~> 0.5.0) + httparty (~> 0.15) turbolinks (2.5.4) coffee-rails turnout (2.4.1) @@ -614,6 +646,7 @@ DEPENDENCIES spring (~> 2.0.1) spring-commands-rspec (~> 1.0.4) sprockets (~> 3.7.2) + translator-text (~> 0.1.0) turbolinks (~> 2.5.3) turnout (~> 2.4.0) uglifier (~> 4.1.2) diff --git a/app/assets/javascripts/forms.js.coffee b/app/assets/javascripts/forms.js.coffee index 34ea71916..5cf403e59 100644 --- a/app/assets/javascripts/forms.js.coffee +++ b/app/assets/javascripts/forms.js.coffee @@ -40,14 +40,15 @@ App.Forms = hideOrShowFieldsAfterSelection: -> $("[name='progress_bar[kind]']").on change: -> - title_field = $("[name^='progress_bar'][name$='[title]']").parent() + locale = App.Globalize.selected_language() + title_field = $(".translatable-fields[data-locale=#{locale}]") if this.value == "primary" title_field.hide() - $("#globalize_locales").hide() + $(".globalize-languages").hide() else title_field.show() - $("#globalize_locales").show() + $(".globalize-languages").show() $("[name='progress_bar[kind]']").change() diff --git a/app/assets/javascripts/globalize.js.coffee b/app/assets/javascripts/globalize.js.coffee index 1238402a2..af320e2e1 100644 --- a/app/assets/javascripts/globalize.js.coffee +++ b/app/assets/javascripts/globalize.js.coffee @@ -1,37 +1,47 @@ App.Globalize = + selected_language: -> + $("#select_language").val() + display_locale: (locale) -> App.Globalize.enable_locale(locale) - $(".js-globalize-locale-link").each -> - if $(this).data("locale") == locale - $(this).show() - App.Globalize.highlight_locale($(this)) - $(".js-globalize-locale option:selected").removeAttr("selected") - return + App.Globalize.add_language(locale) + $(".js-add-language option:selected").removeAttr("selected") display_translations: (locale) -> + $(".js-select-language option[value=#{locale}]").prop("selected", true) $(".js-globalize-attribute").each -> if $(this).data("locale") == locale $(this).show() else $(this).hide() $(".js-delete-language").hide() - $("#js_delete_#{locale}").show() + $(".js-delete-" + locale).show() - highlight_locale: (element) -> - $(".js-globalize-locale-link").removeClass("is-active") - element.addClass("is-active") + add_language: (locale) -> + language_option = $(".js-add-language [value=#{locale}]") + if $(".js-select-language option[value=#{locale}]").length == 0 + option = new Option(language_option.text(), language_option.val()) + $(".js-select-language").append(option) + $(".js-select-language option[value=#{locale}]").prop("selected", true) remove_language: (locale) -> $(".js-globalize-attribute[data-locale=#{locale}]").each -> $(this).val("").hide() - if CKEDITOR.instances[$(this).attr("id")] - CKEDITOR.instances[$(this).attr("id")].setData("") - $(".js-globalize-locale-link[data-locale=#{locale}]").hide() - next = $(".js-globalize-locale-link:visible").first() - App.Globalize.highlight_locale(next) - App.Globalize.display_translations(next.data("locale")) + App.Globalize.resetEditor(this) + + $(".js-select-language option[value=#{locale}]").remove() + next = $(".js-select-language option:not([value=''])").first() + App.Globalize.display_translations(next.val()) App.Globalize.disable_locale(locale) + App.Globalize.update_description() + + if $(".js-select-language option").length == 1 + $(".js-select-language option").prop("selected", true) + + resetEditor: (element) -> + if CKEDITOR.instances[$(element).attr("id")] + CKEDITOR.instances[$(element).attr("id")].setData("") enable_locale: (locale) -> App.Globalize.destroy_locale_field(locale).val(false) @@ -43,8 +53,8 @@ App.Globalize = enabled_locales: -> $.map( - $(".js-globalize-locale-link:visible"), - (element) -> $(element).data("locale") + $(".js-select-language:first option:not([value=''])"), + (element) -> $(element).val() ) destroy_locale_field: (locale) -> @@ -54,20 +64,34 @@ App.Globalize = $("#enabled_translations_#{locale}") refresh_visible_translations: -> - locale = $(".js-globalize-locale-link.is-active").data("locale") + locale = $(".js-select-language").val() App.Globalize.display_translations(locale) + update_description: -> + count = App.Globalize.enabled_locales().length + description = App.Globalize.language_description(count) + $(".js-languages-description").html(description) + $(".js-languages-count").text(count) + + language_description: (count) -> + switch count + when 0 then $(".globalize-languages").data("zero-languages-description") + when 1 then $(".globalize-languages").data("one-languages-description") + else $(".globalize-languages").data("other-languages-description") + initialize: -> - $(".js-globalize-locale").on "change", -> - App.Globalize.display_translations($(this).val()) - App.Globalize.display_locale($(this).val()) - - $(".js-globalize-locale-link").on "click", -> - locale = $(this).data("locale") + $(".js-add-language").on "change", -> + locale = $(this).val() App.Globalize.display_translations(locale) - App.Globalize.highlight_locale($(this)) + App.Globalize.display_locale(locale) + App.Globalize.update_description() - $(".js-delete-language").on "click", -> + $(".js-select-language").on "change", -> + locale = $(this).val() + App.Globalize.display_translations(locale) + + $(".js-delete-language").on "click", (e) -> + e.preventDefault() locale = $(this).data("locale") $(this).hide() App.Globalize.remove_language(locale) diff --git a/app/assets/javascripts/suggest.js.coffee b/app/assets/javascripts/suggest.js.coffee index 854f7ccf1..c8e242cf6 100644 --- a/app/assets/javascripts/suggest.js.coffee +++ b/app/assets/javascripts/suggest.js.coffee @@ -9,11 +9,15 @@ App.Suggest = callback = -> $.ajax url: $this.data("js-url") - data: { search: $this.val() }, - type: "GET", + data: + search: $this.val() + type: "GET" dataType: "html" success: (stHtml) -> js_suggest_selector = $this.data("js-suggest") + if js_suggest_selector.startsWith(".") + locale = $this.closest(".translatable-fields").data("locale") + js_suggest_selector += "[data-locale=#{locale}]" $(js_suggest_selector).html(stHtml) timer = null diff --git a/app/assets/stylesheets/layout.scss b/app/assets/stylesheets/layout.scss index 8e7334935..c65fbe03c 100644 --- a/app/assets/stylesheets/layout.scss +++ b/app/assets/stylesheets/layout.scss @@ -197,6 +197,10 @@ a { padding-top: $line-height; } +.padding-top { + padding-top: $line-height; +} + .light { background: $light; } @@ -474,6 +478,26 @@ header { } } + .remote-translations-button { + + &.callout { + margin: 0; + padding: rem-calc(6); + + [type="submit"] { + background: none; + border: 0; + cursor: pointer; + font-weight: bold; + color: $brand; + + &:hover { + text-decoration: underline; + } + } + } + } + .external-links { float: none; padding: rem-calc(6) 0; @@ -1060,6 +1084,19 @@ form { } } +.translatable-fields { + + &.highlight { + display: inline-block; + padding-top: $line-height; + width: 100%; + } +} + +.translation-locale { + padding-top: $line-height; +} + // 07. Callout // ----------- diff --git a/app/controllers/admin/budget_investments_controller.rb b/app/controllers/admin/budget_investments_controller.rb index c1bfbcf35..a5d2ee21a 100644 --- a/app/controllers/admin/budget_investments_controller.rb +++ b/app/controllers/admin/budget_investments_controller.rb @@ -3,6 +3,7 @@ class Admin::BudgetInvestmentsController < Admin::BaseController include CommentableActions include DownloadSettingsHelper include ChangeLogHelper + include Translatable feature_flag :budgets @@ -81,17 +82,16 @@ class Admin::BudgetInvestmentsController < Admin::BaseController end def load_investments - @investments = Budget::Investment.scoped_filter(params, @current_filter) - .order_filter(params) - + @investments = Budget::Investment.scoped_filter(params, @current_filter).order_filter(params) + @investments = Kaminari.paginate_array(@investments) if @investments.kind_of?(Array) @investments = @investments.page(params[:page]) unless request.format.csv? end def budget_investment_params - params.require(:budget_investment) - .permit(:title, :description, :external_url, :heading_id, :administrator_id, :tag_list, + attributes = [:external_url, :heading_id, :administrator_id, :tag_list, :valuation_tag_list, :incompatible, :visible_to_valuators, :selected, - :milestone_tag_list, tracker_ids: [], valuator_ids: [], valuator_group_ids: []) + :milestone_tag_list, tracker_ids: [], valuator_ids: [], valuator_group_ids: []] + params.require(:budget_investment).permit(attributes, translation_params(Budget::Investment)) end def load_budget diff --git a/app/controllers/admin/hidden_budget_investments_controller.rb b/app/controllers/admin/hidden_budget_investments_controller.rb index 439f3c722..f34818361 100644 --- a/app/controllers/admin/hidden_budget_investments_controller.rb +++ b/app/controllers/admin/hidden_budget_investments_controller.rb @@ -19,7 +19,7 @@ class Admin::HiddenBudgetInvestmentsController < Admin::BaseController end def restore - @investment.restore + @investment.restore(recursive: true) @investment.ignore_flag Activity.log(current_user, :restore, @investment) redirect_to request.query_parameters.merge(action: :index) diff --git a/app/controllers/admin/hidden_comments_controller.rb b/app/controllers/admin/hidden_comments_controller.rb index c3e3bdea9..561fe3aef 100644 --- a/app/controllers/admin/hidden_comments_controller.rb +++ b/app/controllers/admin/hidden_comments_controller.rb @@ -14,7 +14,7 @@ class Admin::HiddenCommentsController < Admin::BaseController end def restore - @comment.restore + @comment.restore(recursive: true) @comment.ignore_flag Activity.log(current_user, :restore, @comment) redirect_to request.query_parameters.merge(action: :index) diff --git a/app/controllers/admin/hidden_debates_controller.rb b/app/controllers/admin/hidden_debates_controller.rb index 77d30b488..3e93db0a6 100644 --- a/app/controllers/admin/hidden_debates_controller.rb +++ b/app/controllers/admin/hidden_debates_controller.rb @@ -17,7 +17,7 @@ class Admin::HiddenDebatesController < Admin::BaseController end def restore - @debate.restore + @debate.restore!(recursive: true) @debate.ignore_flag Activity.log(current_user, :restore, @debate) redirect_to request.query_parameters.merge(action: :index) diff --git a/app/controllers/admin/hidden_proposals_controller.rb b/app/controllers/admin/hidden_proposals_controller.rb index 48c910c0c..7442c0626 100644 --- a/app/controllers/admin/hidden_proposals_controller.rb +++ b/app/controllers/admin/hidden_proposals_controller.rb @@ -18,7 +18,7 @@ class Admin::HiddenProposalsController < Admin::BaseController end def restore - @proposal.restore + @proposal.restore(recursive: true) @proposal.ignore_flag Activity.log(current_user, :restore, @proposal) redirect_to request.query_parameters.merge(action: :index) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 794dcd26b..5451451ff 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,6 +1,7 @@ require "application_responder" class ApplicationController < ActionController::Base + include GlobalizeFallbacks include HasFilters include HasOrders include AccessDeniedHandler @@ -14,7 +15,6 @@ class ApplicationController < ActionController::Base before_action :track_email_campaign before_action :set_return_url before_action :set_current_user - before_action :set_fallbacks_to_all_available_locales check_authorization unless: :devise_controller? self.responder = ApplicationResponder @@ -124,8 +124,4 @@ class ApplicationController < ActionController::Base def set_current_user User.current_user = current_user end - - def set_fallbacks_to_all_available_locales - Globalize.set_fallbacks_to_all_available_locales - end end diff --git a/app/controllers/budgets/investments_controller.rb b/app/controllers/budgets/investments_controller.rb index 1aea05085..5a57dd1f4 100644 --- a/app/controllers/budgets/investments_controller.rb +++ b/app/controllers/budgets/investments_controller.rb @@ -6,6 +6,7 @@ module Budgets include FlagActions include RandomSeed include ImageAttributes + include Translatable PER_PAGE = 10 @@ -48,6 +49,7 @@ module Budgets load_investment_votes(@investments) @tag_cloud = tag_cloud + @remote_translations = detect_remote_translations(@investments) end def new @@ -60,6 +62,7 @@ module Budgets set_comment_flags(@comment_tree.comments) load_investment_votes(@investment) @investment_ids = [@investment.id] + @remote_translations = detect_remote_translations([@investment], @comment_tree.comments) end def create @@ -122,12 +125,12 @@ module Budgets end def investment_params - params.require(:budget_investment) - .permit(:title, :description, :heading_id, :tag_list, + attributes = [:heading_id, :tag_list, :organization_name, :location, :terms_of_service, :skip_map, image_attributes: image_attributes, documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy], - map_location_attributes: [:latitude, :longitude, :zoom]) + map_location_attributes: [:latitude, :longitude, :zoom]] + params.require(:budget_investment).permit(attributes, translation_params(Budget::Investment)) end def load_ballot diff --git a/app/controllers/concerns/commentable_actions.rb b/app/controllers/concerns/commentable_actions.rb index 66e2456de..2c6d1da81 100644 --- a/app/controllers/concerns/commentable_actions.rb +++ b/app/controllers/concerns/commentable_actions.rb @@ -3,6 +3,7 @@ module CommentableActions include Polymorphic include Search include DownloadSettingsHelper + include RemotelyTranslatable def index @resources = resource_model.all @@ -23,6 +24,8 @@ module CommentableActions set_resource_votes(@resources) set_resources_instance + @remote_translations = detect_remote_translations(@resources, featured_proposals) + respond_to do |format| format.html format.csv {send_data to_csv(resources_csv, resource_model), @@ -38,6 +41,7 @@ module CommentableActions @comment_tree = CommentTree.new(@commentable, params[:page], @current_order) set_comment_flags(@comment_tree.comments) set_resource_instance + @remote_translations = detect_remote_translations([@resource], @comment_tree.comments) end def new @@ -132,4 +136,7 @@ module CommentableActions end end + def featured_proposals + @featured_proposals ||= [] + end end diff --git a/app/controllers/concerns/globalize_fallbacks.rb b/app/controllers/concerns/globalize_fallbacks.rb new file mode 100644 index 000000000..386bb3ae1 --- /dev/null +++ b/app/controllers/concerns/globalize_fallbacks.rb @@ -0,0 +1,13 @@ +module GlobalizeFallbacks + extend ActiveSupport::Concern + + included do + before_action :initialize_globalize_fallbacks + end + + private + + def initialize_globalize_fallbacks + Globalize.set_fallbacks_to_all_available_locales + end +end diff --git a/app/controllers/concerns/remotely_translatable.rb b/app/controllers/concerns/remotely_translatable.rb new file mode 100644 index 000000000..4f030ff6c --- /dev/null +++ b/app/controllers/concerns/remotely_translatable.rb @@ -0,0 +1,29 @@ +module RemotelyTranslatable + + private + + def detect_remote_translations(*args) + return [] unless Setting["feature.remote_translations"].present? + + resources_groups(*args).flatten.select { |resource| translation_empty?(resource) }.map do |resource| + remote_translation_for(resource) + end + end + + def remote_translation_for(resource) + { "remote_translatable_id" => resource.id.to_s, + "remote_translatable_type" => resource.class.to_s, + "locale" => I18n.locale } + end + + def translation_empty?(resource) + resource.translations.where(locale: I18n.locale).empty? + end + + def resources_groups(*args) + feeds = args.detect { |arg| arg&.first.class == Widget::Feed } || [] + + args.compact - [feeds] + feeds.map(&:items) + end + +end diff --git a/app/controllers/concerns/translatable.rb b/app/controllers/concerns/translatable.rb index 94cdcaaab..533b8db22 100644 --- a/app/controllers/concerns/translatable.rb +++ b/app/controllers/concerns/translatable.rb @@ -3,10 +3,13 @@ module Translatable private - def translation_params(resource_model) - { - translations_attributes: [:id, :_destroy, :locale] + - resource_model.translated_attribute_names - } + def translation_params(resource_model, options = {}) + attributes = [:id, :locale, :_destroy] + if options[:only] + attributes += [*options[:only]] + else + attributes += resource_model.translated_attribute_names + end + { translations_attributes: attributes - [*options[:except]] } end end diff --git a/app/controllers/debates_controller.rb b/app/controllers/debates_controller.rb index b10e28b88..c0def9803 100644 --- a/app/controllers/debates_controller.rb +++ b/app/controllers/debates_controller.rb @@ -2,6 +2,7 @@ class DebatesController < ApplicationController include FeatureFlags include CommentableActions include FlagActions + include Translatable before_action :parse_tag_filter, only: :index before_action :authenticate_user!, except: [:index, :show, :map] @@ -55,7 +56,8 @@ class DebatesController < ApplicationController private def debate_params - params.require(:debate).permit(:title, :description, :tag_list, :terms_of_service) + attributes = [:tag_list, :terms_of_service] + params.require(:debate).permit(attributes, translation_params(Debate)) end def resource_model diff --git a/app/controllers/management/base_controller.rb b/app/controllers/management/base_controller.rb index 4314b2aa7..9f45fab39 100644 --- a/app/controllers/management/base_controller.rb +++ b/app/controllers/management/base_controller.rb @@ -1,4 +1,5 @@ class Management::BaseController < ActionController::Base + include GlobalizeFallbacks layout "management" before_action :verify_manager diff --git a/app/controllers/management/budgets/investments_controller.rb b/app/controllers/management/budgets/investments_controller.rb index 79a65cf15..da7bb117e 100644 --- a/app/controllers/management/budgets/investments_controller.rb +++ b/app/controllers/management/budgets/investments_controller.rb @@ -1,4 +1,5 @@ class Management::Budgets::InvestmentsController < Management::BaseController + include Translatable before_action :load_budget load_resource :budget @@ -53,8 +54,8 @@ class Management::Budgets::InvestmentsController < Management::BaseController end def investment_params - params.require(:budget_investment).permit(:title, :description, :external_url, :heading_id, - :tag_list, :organization_name, :location, :skip_map) + attributes = [:external_url, :heading_id, :tag_list, :organization_name, :location, :skip_map] + params.require(:budget_investment).permit(attributes, translation_params(Budget::Investment)) end def only_verified_users diff --git a/app/controllers/management/proposals_controller.rb b/app/controllers/management/proposals_controller.rb index f24e94303..93e20f690 100644 --- a/app/controllers/management/proposals_controller.rb +++ b/app/controllers/management/proposals_controller.rb @@ -1,6 +1,7 @@ class Management::ProposalsController < Management::BaseController include HasOrders include CommentableActions + include Translatable before_action :only_verified_users, except: :print before_action :set_proposal, only: [:vote, :show] @@ -52,10 +53,10 @@ class Management::ProposalsController < Management::BaseController end def proposal_params - params.require(:proposal).permit(:title, :summary, :description, :video_url, - :responsible_name, :tag_list, :terms_of_service, :geozone_id, - :skip_map, - map_location_attributes: [:latitude, :longitude, :zoom]) + attributes = [:video_url, :responsible_name, :tag_list, + :terms_of_service, :geozone_id, + :skip_map, map_location_attributes: [:latitude, :longitude, :zoom]] + params.require(:proposal).permit(attributes, translation_params(Proposal)) end def resource_model diff --git a/app/controllers/management/sessions_controller.rb b/app/controllers/management/sessions_controller.rb index a88c1de9f..83e364e00 100644 --- a/app/controllers/management/sessions_controller.rb +++ b/app/controllers/management/sessions_controller.rb @@ -1,6 +1,7 @@ require "manager_authenticator" class Management::SessionsController < ActionController::Base + include GlobalizeFallbacks include AccessDeniedHandler def create diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb index fc596c5f0..6f35d44be 100644 --- a/app/controllers/proposals_controller.rb +++ b/app/controllers/proposals_controller.rb @@ -3,6 +3,7 @@ class ProposalsController < ApplicationController include CommentableActions include FlagActions include ImageAttributes + include Translatable before_action :parse_tag_filter, only: :index before_action :load_categories, only: [:index, :new, :create, :edit, :map, :summary] @@ -37,7 +38,6 @@ class ProposalsController < ApplicationController def create @proposal = Proposal.new(proposal_params.merge(author: current_user)) - if @proposal.save redirect_to created_proposal_path(@proposal), notice: I18n.t("flash.actions.create.proposal") else @@ -62,7 +62,7 @@ class ProposalsController < ApplicationController end def retire - if valid_retired_params? && @proposal.update(retired_params.merge(retired_at: Time.current)) + if @proposal.update(retired_params.merge(retired_at: Time.current)) redirect_to proposal_path(@proposal), notice: t("proposals.notice.retired") else render action: :retire_form @@ -98,22 +98,20 @@ class ProposalsController < ApplicationController private def proposal_params - params.require(:proposal).permit(:title, :summary, :description, :video_url, - :responsible_name, :tag_list, :terms_of_service, - :geozone_id, :skip_map, image_attributes: image_attributes, - documents_attributes: [:id, :title, :attachment, - :cached_attachment, :user_id, :_destroy], - map_location_attributes: [:latitude, :longitude, :zoom]) + attributes = [:video_url,:responsible_name, :tag_list, + :terms_of_service, :geozone_id, :skip_map, + image_attributes: image_attributes, + documents_attributes: [:id, :title, :attachment, :cached_attachment, + :user_id, :_destroy], + map_location_attributes: [:latitude, :longitude, :zoom]] + translations_attributes = translation_params(Proposal, except: :retired_explanation) + params.require(:proposal).permit(attributes, translations_attributes) end def retired_params - params.require(:proposal).permit(:retired_reason, :retired_explanation) - end - - def valid_retired_params? - @proposal.errors.add(:retired_reason, I18n.t("errors.messages.blank")) if params[:proposal][:retired_reason].blank? - @proposal.errors.add(:retired_explanation, I18n.t("errors.messages.blank")) if params[:proposal][:retired_explanation].blank? - @proposal.errors.empty? + attributes = [:retired_reason] + translations_attributes = translation_params(Proposal, only: :retired_explanation) + params.require(:proposal).permit(attributes, translations_attributes) end def resource_model diff --git a/app/controllers/remote_translations_controller.rb b/app/controllers/remote_translations_controller.rb new file mode 100644 index 000000000..d811d2f5c --- /dev/null +++ b/app/controllers/remote_translations_controller.rb @@ -0,0 +1,34 @@ +class RemoteTranslationsController < ApplicationController + skip_authorization_check + respond_to :html, :js + + before_action :set_remote_translations, only: :create + + def create + @remote_translations.each do |remote_translation| + RemoteTranslation.create(remote_translation) unless translations_enqueued?(remote_translation) + end + redirect_to request.referer, notice: t("remote_translations.create.enqueue_remote_translation") + end + + private + + def remote_translations_params + params.permit(:remote_translations) + end + + def set_remote_translations + remote_translations = remote_translations_params["remote_translations"] + decoded_remote_translations = ActiveSupport::JSON.decode(remote_translations) + @remote_translations = decoded_remote_translations.map{ |remote_translation| + remote_translation.slice("remote_translatable_id", + "remote_translatable_type", + "locale") + } + end + + def translations_enqueued?(remote_translation) + RemoteTranslation.remote_translation_enqueued?(remote_translation) + end + +end diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index eb009746a..b6bb138c4 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -1,4 +1,6 @@ class WelcomeController < ApplicationController + include RemotelyTranslatable + skip_authorization_check before_action :set_user_recommendations, only: :index, if: :current_user before_action :authenticate_user!, only: :welcome @@ -10,6 +12,9 @@ class WelcomeController < ApplicationController @feeds = Widget::Feed.active @cards = Widget::Card.body @banners = Banner.in_section("homepage").with_active + @remote_translations = detect_remote_translations(@feeds, + @recommended_debates, + @recommended_proposals) end def welcome diff --git a/app/helpers/globalize_helper.rb b/app/helpers/globalize_helper.rb index 92d02b63e..65021b350 100644 --- a/app/helpers/globalize_helper.rb +++ b/app/helpers/globalize_helper.rb @@ -1,46 +1,134 @@ module GlobalizeHelper - def options_for_locale_select - options_for_select(locale_options, nil) + def options_for_select_language(resource) + options_for_select(available_locales(resource), selected_locale(resource)) end - def locale_options - I18n.available_locales.map do |locale| - [name_for_locale(locale), locale] + def available_locales(resource) + I18n.available_locales.select{ |locale| enabled_locale?(resource, locale) }.map do |locale| + [name_for_locale(locale), locale , { data: { locale: locale } }] end end - def display_translation?(resource, locale) - if !resource || resource.translations.blank? || - resource.locales_not_marked_for_destruction.include?(I18n.locale) - locale == I18n.locale + def enabled_locale?(resource, locale) + return site_customization_enable_translation?(locale) if resource.blank? + + if resource.locales_not_marked_for_destruction.any? + resource.locales_not_marked_for_destruction.include?(locale) + elsif resource.locales_persisted_and_marked_for_destruction.any? + locale == first_marked_for_destruction_translation(resource) else - locale == resource.translations.first.locale + locale == I18n.locale end end + def selected_locale(resource) + return first_i18n_content_translation_locale if resource.blank? + + if resource.locales_not_marked_for_destruction.any? + first_translation(resource) + elsif resource.locales_persisted_and_marked_for_destruction.any? + first_marked_for_destruction_translation(resource) + else + I18n.locale + end + end + + def first_i18n_content_translation_locale + if I18nContentTranslation.existing_languages.count == 0 || + I18nContentTranslation.existing_languages.include?(I18n.locale) + I18n.locale + else + I18nContentTranslation.existing_languages.first + end + end + + def first_translation(resource) + if resource.locales_not_marked_for_destruction.include? I18n.locale + I18n.locale + else + resource.locales_not_marked_for_destruction.first + end + end + + def first_marked_for_destruction_translation(resource) + if resource.locales_persisted_and_marked_for_destruction.include? I18n.locale + I18n.locale + else + resource.locales_persisted_and_marked_for_destruction.first + end + end + + def translations_for_locale?(resource) + resource.locales_not_marked_for_destruction.any? + end + + def selected_languages_description(resource) + t("shared.translations.languages_in_use_html", count: active_languages_count(resource)) + end + + def select_language_error(resource) + return if resource.blank? + + current_translation = resource.translation_for(selected_locale(resource)) + if current_translation.errors.added? :base, :translations_too_short + content_tag :div, class: "small error" do + current_translation.errors[:base].join(", ") + end + end + end + + def active_languages_count(resource) + if resource.blank? + no_resource_languages_count + elsif resource.locales_not_marked_for_destruction.size > 0 + resource.locales_not_marked_for_destruction.size + else + 1 + end + end + + def no_resource_languages_count + count = I18nContentTranslation.existing_languages.count + count > 0 ? count : 1 + end + def display_translation_style(resource, locale) "display: none;" unless display_translation?(resource, locale) end - def translation_enabled_tag(locale, enabled) - hidden_field_tag("enabled_translations[#{locale}]", (enabled ? 1 : 0)) - end + def display_translation?(resource, locale) + return locale == I18n.locale if resource.blank? - def enable_translation_style(resource, locale) - "display: none;" unless enable_locale?(resource, locale) - end - - def enable_locale?(resource, locale) - if resource.translations.any? - resource.locales_not_marked_for_destruction.include?(locale) + if resource.locales_not_marked_for_destruction.any? + locale == first_translation(resource) + elsif resource.locales_persisted_and_marked_for_destruction.any? + locale == first_marked_for_destruction_translation(resource) else locale == I18n.locale end end - def highlight_class(resource, locale) - "is-active" if display_translation?(resource, locale) + def display_destroy_locale_style(resource, locale) + "display: none;" unless display_destroy_locale_link?(resource, locale) + end + + def display_destroy_locale_link?(resource, locale) + selected_locale(resource) == locale + end + + def options_for_add_language + options_for_select(all_language_options, nil) + end + + def all_language_options + I18n.available_locales.map do |locale| + [name_for_locale(locale), locale] + end + end + + def translation_enabled_tag(locale, enabled) + hidden_field_tag("enabled_translations[#{locale}]", (enabled ? 1 : 0)) end def globalize(locale, &block) @@ -48,9 +136,4 @@ module GlobalizeHelper yield end end - - def same_locale?(locale1, locale2) - locale1 == locale2 - end - end diff --git a/app/helpers/proposals_helper.rb b/app/helpers/proposals_helper.rb index ecd8a1490..3879d4679 100644 --- a/app/helpers/proposals_helper.rb +++ b/app/helpers/proposals_helper.rb @@ -64,6 +64,10 @@ module ProposalsHelper proposals_current_view == "default" ? "minimal" : "default" end + def summary_help_text_id(translations_form) + "summary-help-text-#{translations_form.locale}" + end + def link_to_toggle_proposal_selection(proposal) if proposal.selected? button_text = t("admin.proposals.index.selected") diff --git a/app/helpers/remote_translations_helper.rb b/app/helpers/remote_translations_helper.rb new file mode 100644 index 000000000..d9435f833 --- /dev/null +++ b/app/helpers/remote_translations_helper.rb @@ -0,0 +1,12 @@ +module RemoteTranslationsHelper + + def display_remote_translation_info?(remote_translations, locale) + remote_translations.present? && RemoteTranslations::Microsoft::AvailableLocales.include_locale?(locale) + end + + def display_remote_translation_button?(remote_translations) + remote_translations.none? do |remote_translation| + RemoteTranslation.remote_translation_enqueued?(remote_translation) + end + end +end diff --git a/app/helpers/text_with_links_helper.rb b/app/helpers/text_with_links_helper.rb index 9144bdd6b..b59c6ae7f 100644 --- a/app/helpers/text_with_links_helper.rb +++ b/app/helpers/text_with_links_helper.rb @@ -8,6 +8,7 @@ module TextWithLinksHelper def safe_html_with_links(html) return if html.nil? + html = ActiveSupport::SafeBuffer.new(html) if html.is_a?(String) return html.html_safe unless html.html_safe? Rinku.auto_link(html, :all, 'target="_blank" rel="nofollow"').html_safe end diff --git a/app/helpers/translatable_form_helper.rb b/app/helpers/translatable_form_helper.rb index fdee3bf34..458c7a929 100644 --- a/app/helpers/translatable_form_helper.rb +++ b/app/helpers/translatable_form_helper.rb @@ -6,15 +6,27 @@ module TranslatableFormHelper end end + def translations_interface_enabled? + Setting["feature.translation_interface"].present? || backend_translations_enabled? + end + + def backend_translations_enabled? + (controller.class.parents & [Admin, Management, Valuation, Tracking]).any? + end + + def highlight_translation_html_class + "highlight" if translations_interface_enabled? + end + class TranslatableFormBuilder < FoundationRailsHelper::FormBuilder attr_accessor :translations def translatable_fields(&block) @translations = {} - @object.globalize_locales.map do |locale| + visible_locales.map do |locale| @translations[locale] = translation_for(locale) end - @object.globalize_locales.map do |locale| + visible_locales.map do |locale| Globalize.with_locale(locale) { fields_for_locale(locale, &block) } end.join.html_safe end @@ -26,6 +38,7 @@ module TranslatableFormHelper @template.content_tag :div, translations_options(translations_form.object, locale) do @template.concat translations_form.hidden_field( :_destroy, + value: !@template.enabled_locale?(translations_form.object.globalized_model, locale), data: { locale: locale } ) @@ -52,15 +65,17 @@ module TranslatableFormHelper def new_translation_for(locale) @object.translations.new(locale: locale).tap do |translation| - unless locale == I18n.locale && no_other_translations?(translation) - translation.mark_for_destruction - end + translation.mark_for_destruction end end + def highlight_translation_html_class + @template.highlight_translation_html_class + end + def translations_options(resource, locale) { - class: "translatable-fields js-globalize-attribute", + class: "translatable-fields js-globalize-attribute #{highlight_translation_html_class}", style: @template.display_translation_style(resource.globalized_model, locale), data: { locale: locale } } @@ -69,6 +84,14 @@ module TranslatableFormHelper def no_other_translations?(translation) (@object.translations - [translation]).reject(&:_destroy).empty? end + + def visible_locales + if @template.translations_interface_enabled? + @object.globalize_locales + else + [I18n.locale] + end + end end class TranslationsFieldsBuilder < FoundationRailsHelper::FormBuilder diff --git a/app/models/budget.rb b/app/models/budget.rb index 133956b07..4904f3923 100644 --- a/app/models/budget.rb +++ b/app/models/budget.rb @@ -22,8 +22,6 @@ class Budget < ApplicationRecord CURRENCY_SYMBOLS = %w(€ $ £ ¥).freeze - before_validation :assign_model_to_translations - validates_translation :name, presence: true validates :phase, inclusion: { in: Budget::Phase::PHASE_KINDS } validates :currency_symbol, presence: true @@ -231,4 +229,16 @@ class Budget < ApplicationRecord slug.nil? || drafting? end + class Translation < Globalize::ActiveRecord::Translation + validate :name_uniqueness_by_budget + + def name_uniqueness_by_budget + if Budget.joins(:translations) + .where(name: name) + .where.not("budget_translations.budget_id": budget_id).any? + errors.add(:name, I18n.t("errors.messages.taken")) + end + end + end + end diff --git a/app/models/budget/group.rb b/app/models/budget/group.rb index 43d28a0ae..741040c78 100644 --- a/app/models/budget/group.rb +++ b/app/models/budget/group.rb @@ -22,8 +22,6 @@ class Budget has_many :headings, dependent: :destroy - before_validation :assign_model_to_translations - validates_translation :name, presence: true validates :budget_id, presence: true validates :slug, presence: true, format: /\A[a-z0-9\-_]+\z/ @@ -42,5 +40,18 @@ class Budget slug.nil? || budget.drafting? end + class Translation < Globalize::ActiveRecord::Translation + delegate :budget, to: :globalized_model + + validate :name_uniqueness_by_budget + + def name_uniqueness_by_budget + if budget.groups.joins(:translations) + .where(name: name) + .where.not("budget_group_translations.budget_group_id": budget_group_id).any? + errors.add(:name, I18n.t("errors.messages.taken")) + end + end + end end end diff --git a/app/models/budget/heading.rb b/app/models/budget/heading.rb index 7b33c4e54..0221061d7 100644 --- a/app/models/budget/heading.rb +++ b/app/models/budget/heading.rb @@ -26,8 +26,6 @@ class Budget has_many :investments has_many :content_blocks - before_validation :assign_model_to_translations - validates_translation :name, presence: true validates :group_id, presence: true validates :price, presence: true @@ -62,5 +60,19 @@ class Budget slug.nil? || budget.drafting? end + class Translation < Globalize::ActiveRecord::Translation + delegate :budget, to: :globalized_model + + validate :name_uniqueness_by_budget + + def name_uniqueness_by_budget + if budget.headings + .joins(:translations) + .where(name: name) + .where.not("budget_heading_translations.budget_heading_id": budget_heading_id).any? + errors.add(:name, I18n.t("errors.messages.taken")) + end + end + end end end diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb index 9da713c84..aa83a499a 100644 --- a/app/models/budget/investment.rb +++ b/app/models/budget/investment.rb @@ -1,7 +1,7 @@ class Budget require "csv" class Investment < ApplicationRecord - SORTING_OPTIONS = {id: "id", title: "title", supports: "cached_votes_up"}.freeze + SORTING_OPTIONS = { id: "id", supports: "cached_votes_up" }.freeze include ActiveModel::Dirty include Rails.application.routes.url_helpers @@ -28,6 +28,10 @@ class Budget extend DownloadSettings::BudgetInvestmentCsv + translates :title, touch: true + translates :description, touch: true + include Globalizable + belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id" belongs_to :heading belongs_to :group @@ -48,15 +52,13 @@ class Budget delegate :name, :email, to: :author, prefix: true - validates :title, presence: true + validates_translation :title, presence: true, length: { in: 4..Budget::Investment.title_max_length } + validates_translation :description, presence: true, length: { maximum: Budget::Investment.description_max_length } + validates :author, presence: true - validates :description, presence: true validates :heading_id, presence: true validates :unfeasibility_explanation, presence: { if: :unfeasibility_explanation_required? } validates :price, presence: { if: :price_required? } - - validates :title, length: { in: 4..Budget::Investment.title_max_length } - validates :description, length: { maximum: Budget::Investment.description_max_length } validates :terms_of_service, acceptance: { allow_nil: false }, on: :create scope :sort_by_confidence_score, -> { reorder(confidence_score: :desc, id: :desc) } @@ -64,7 +66,6 @@ class Budget scope :sort_by_price, -> { reorder(price: :desc, confidence_score: :desc, id: :desc) } scope :sort_by_id, -> { order("id DESC") } - scope :sort_by_title, -> { order("title ASC") } scope :sort_by_supports, -> { order("cached_votes_up DESC") } scope :valuation_open, -> { where(valuation_finished: false) } @@ -117,6 +118,10 @@ class Budget budget_investment_path(budget, self) end + def self.sort_by_title + with_translation.sort_by(&:title) + end + def self.filter_params(params) params.permit(%i[heading_id group_id administrator_id tag_name valuator_id]) end @@ -162,10 +167,12 @@ class Budget def self.order_filter(params) sorting_key = params[:sort_by]&.downcase&.to_sym allowed_sort_option = SORTING_OPTIONS[sorting_key] + direction = params[:direction] == "desc" ? "desc" : "asc" if allowed_sort_option.present? - direction = params[:direction] == "desc" ? "desc" : "asc" order("#{allowed_sort_option} #{direction}") + elsif sorting_key == :title + direction == "asc" ? sort_by_title : sort_by_title.reverse else order(cached_votes_up: :desc).order(id: :desc) end @@ -184,20 +191,17 @@ class Budget end def self.search_by_title_or_id(title_or_id, results) - if title_or_id =~ /^[0-9]+$/ - results.where(id: title_or_id) - else - results.where("title ILIKE ?", "%#{title_or_id}%") - end + return results.where(id: title_or_id) if title_or_id =~ /^[0-9]+$/ + + results.with_translations(Globalize.fallbacks(I18n.locale)). + where("budget_investment_translations.title ILIKE ?", "%#{title_or_id}%") end def searchable_values - { title => "A", - author.username => "B", - heading.try(:name) => "B", - tag_list.join(" ") => "B", - description => "C" - } + { author.username => "B", + heading.name => "B", + tag_list.join(" ") => "B" + }.merge(searchable_globalized_values) end def self.search(terms) @@ -413,5 +417,10 @@ class Budget end end end + + def searchable_translations_definitions + { title => "A", + description => "D" } + end end end diff --git a/app/models/budget/phase.rb b/app/models/budget/phase.rb index 125368ccd..5d28e65ab 100644 --- a/app/models/budget/phase.rb +++ b/app/models/budget/phase.rb @@ -100,5 +100,14 @@ class Budget PHASE_KINDS.index(kind) >= PHASE_KINDS.index(phase) end + class Translation < Globalize::ActiveRecord::Translation + before_validation :sanitize_description + + private + + def sanitize_description + self.description = WYSIWYGSanitizer.new.sanitize(description) + end + end end end diff --git a/app/models/comment.rb b/app/models/comment.rb index e5b83e818..e80a5e048 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -18,7 +18,10 @@ class Comment < ApplicationRecord attr_accessor :as_moderator, :as_administrator - validates :body, presence: true + translates :body, touch: true + include Globalizable + + validates_translation :body, presence: true validates :user, presence: true validates :commentable_type, inclusion: { in: COMMENTABLE_TYPES } diff --git a/app/models/concerns/globalizable.rb b/app/models/concerns/globalizable.rb index f963787c7..9999e3502 100644 --- a/app/models/concerns/globalizable.rb +++ b/app/models/concerns/globalizable.rb @@ -1,27 +1,101 @@ module Globalizable + MIN_TRANSLATIONS = 1 extend ActiveSupport::Concern included do globalize_accessors accepts_nested_attributes_for :translations, allow_destroy: true - def locales_not_marked_for_destruction - translations.reject(&:_destroy).map(&:locale) - end - - def assign_model_to_translations - translations.each { |translation| translation.globalized_model = self } - end + validate :check_translations_number, on: :update, if: :translations_required? + after_validation :copy_error_to_current_translation, on: :update def description self.read_attribute(:description).try :html_safe end + + def locales_not_marked_for_destruction + translations.reject(&:marked_for_destruction?).map(&:locale) + end + + def locales_marked_for_destruction + I18n.available_locales - locales_not_marked_for_destruction + end + + def locales_persisted_and_marked_for_destruction + translations.select{|t| t.persisted? && t.marked_for_destruction? }.map(&:locale) + end + + def translations_required? + translated_attribute_names.any?{|attr| required_attribute?(attr)} + end + + if self.paranoid? && translation_class.attribute_names.include?("hidden_at") + translation_class.send :acts_as_paranoid, column: :hidden_at + end + + scope :with_translation, -> { joins("LEFT OUTER JOIN #{translations_table_name} ON #{table_name}.id = #{translations_table_name}.#{reflections["translations"].foreign_key} AND #{translations_table_name}.locale='#{I18n.locale }'") } + + private + + def required_attribute?(attribute) + presence_validators = [ActiveModel::Validations::PresenceValidator, + ActiveRecord::Validations::PresenceValidator] + + attribute_validators(attribute).any?{|validator| presence_validators.include? validator } + end + + def attribute_validators(attribute) + self.class.validators_on(attribute).map(&:class) + end + + def check_translations_number + errors.add(:base, :translations_too_short) unless traslations_count_valid? + end + + def traslations_count_valid? + translations.reject(&:marked_for_destruction?).count >= MIN_TRANSLATIONS + end + + def copy_error_to_current_translation + return unless errors.added?(:base, :translations_too_short) + + if locales_persisted_and_marked_for_destruction.include?(I18n.locale) + locale = I18n.locale + else + locale = locales_persisted_and_marked_for_destruction.first + end + + translation = translation_for(locale) + translation.errors.add(:base, :translations_too_short) + end + + def searchable_globalized_values + values = {} + translations.each do |translation| + Globalize.with_locale(translation.locale) do + values.merge! searchable_translations_definitions + end + end + values + end end class_methods do def validates_translation(method, options = {}) validates(method, options.merge(if: lambda { |resource| resource.translations.blank? })) - translation_class.instance_eval { validates method, options } + if options.include?(:length) + lenght_validate = { length: options[:length] } + translation_class.instance_eval do + validates method, lenght_validate.merge(if: lambda { |translation| translation.locale == I18n.default_locale }) + end + if options.count > 1 + translation_class.instance_eval do + validates method, options.reject { |key| key == :length } + end + end + else + translation_class.instance_eval { validates method, options } + end end def translation_class_delegate(method) diff --git a/app/models/concerns/notifiable.rb b/app/models/concerns/notifiable.rb index b10c57f70..aa7d4d3bc 100644 --- a/app/models/concerns/notifiable.rb +++ b/app/models/concerns/notifiable.rb @@ -12,6 +12,10 @@ module Notifiable end end + def notifiable_body + body if attribute_names.include?("body") + end + def notifiable_available? case self.class.name when "ProposalNotification" diff --git a/app/models/debate.rb b/app/models/debate.rb index 3f1ca7d76..b3a23200a 100644 --- a/app/models/debate.rb +++ b/app/models/debate.rb @@ -20,6 +20,10 @@ class Debate < ApplicationRecord acts_as_paranoid column: :hidden_at include ActsAsParanoidAliases + translates :title, touch: true + translates :description, touch: true + include Globalizable + belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id" belongs_to :geozone has_many :comments, as: :commentable @@ -27,13 +31,10 @@ class Debate < ApplicationRecord extend DownloadSettings::DebateCsv delegate :name, :email, to: :author, prefix: true - validates :title, presence: true - validates :description, presence: true + validates_translation :title, presence: true, length: { in: 4..Debate.title_max_length } + validates_translation :description, presence: true, length: { in: 10..Debate.description_max_length } validates :author, presence: true - validates :title, length: { in: 4..Debate.title_max_length } - validates :description, length: { in: 10..Debate.description_max_length } - validates :terms_of_service, acceptance: { allow_nil: false }, on: :create before_save :calculate_hot_score, :calculate_confidence_score @@ -64,13 +65,17 @@ class Debate < ApplicationRecord .where("author_id != ?", user.id) end + def searchable_translations_definitions + { title => "A", + description => "D" } + end + def searchable_values - { title => "A", + { author.username => "B", tag_list.join(" ") => "B", geozone.try(:name) => "B", - description => "D" - } + }.merge!(searchable_globalized_values) end def self.search(terms) diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 52f8ccb29..d4219c004 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -11,8 +11,6 @@ class Milestone < ApplicationRecord validates :milestoneable, presence: true validates :publication_date, presence: true - - before_validation :assign_model_to_translations validates_translation :description, presence: true, unless: -> { status_id.present? } scope :order_by_publication_date, -> { order(publication_date: :asc, created_at: :asc) } diff --git a/app/models/notification.rb b/app/models/notification.rb index 738e5ab5f..e5a8e2b95 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -11,8 +11,9 @@ class Notification < ApplicationRecord scope :recent, -> { order(id: :desc) } scope :for_render, -> { includes(:notifiable) } - delegate :notifiable_title, :notifiable_available?, :check_availability, - :linkable_resource, to: :notifiable, allow_nil: true + delegate :notifiable_title, :notifiable_body, :notifiable_available?, + :check_availability, :linkable_resource, + to: :notifiable, allow_nil: true def mark_as_read update(read_at: Time.current) diff --git a/app/models/progress_bar.rb b/app/models/progress_bar.rb index c0bacc7ba..e9994f011 100644 --- a/app/models/progress_bar.rb +++ b/app/models/progress_bar.rb @@ -18,7 +18,6 @@ class ProgressBar < ApplicationRecord } validates :percentage, presence: true, inclusion: RANGE, numericality: { only_integer: true } - before_validation :assign_model_to_translations validates_translation :title, presence: true, unless: :primary? end diff --git a/app/models/proposal.rb b/app/models/proposal.rb index e0f707918..497d8181e 100644 --- a/app/models/proposal.rb +++ b/app/models/proposal.rb @@ -28,6 +28,13 @@ class Proposal < ApplicationRecord RETIRE_OPTIONS = %w[duplicated started unfeasible done other] + translates :title, touch: true + translates :description, touch: true + translates :summary, touch: true + translates :retired_explanation, touch: true + include Globalizable + translation_class_delegate :retired_at + belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id" belongs_to :geozone has_many :comments, as: :commentable, dependent: :destroy @@ -39,18 +46,16 @@ class Proposal < ApplicationRecord extend DownloadSettings::ProposalCsv delegate :name, :email, to: :author, prefix: true - extend DownloadSettings::ProposalCsv - delegate :name, :email, to: :author, prefix: true + validates_translation :title, presence: true, length: { in: 4..Proposal.title_max_length } + validates_translation :description, length: { maximum: Proposal.description_max_length } + validates_translation :summary, presence: true + validates_translation :retired_explanation, presence: true, unless: -> { retired_at.blank? } - validates :title, presence: true - validates :summary, presence: true validates :author, presence: true validates :responsible_name, presence: true, unless: :skip_user_verification? - validates :title, length: { in: 4..Proposal.title_max_length } - validates :description, length: { maximum: Proposal.description_max_length } validates :responsible_name, length: { in: 6..Proposal.responsible_name_max_length }, unless: :skip_user_verification? - validates :retired_reason, inclusion: { in: RETIRE_OPTIONS, allow_nil: true } + validates :retired_reason, presence: true, inclusion: { in: RETIRE_OPTIONS }, unless: -> { retired_at.blank? } validates :terms_of_service, acceptance: { allow_nil: false }, on: :create @@ -120,14 +125,18 @@ class Proposal < ApplicationRecord "#{id}-#{title}".parameterize end + def searchable_translations_definitions + { title => "A", + summary => "C", + description => "D" } + end + def searchable_values - { title => "A", - author.username => "B", - tag_list.join(" ") => "B", - geozone.try(:name) => "B", - summary => "C", - description => "D" - } + { + author.username => "B", + tag_list.join(" ") => "B", + geozone.try(:name) => "B" + }.merge!(searchable_globalized_values) end def self.search(terms) @@ -264,5 +273,4 @@ class Proposal < ApplicationRecord self.responsible_name = author.document_number end end - end diff --git a/app/models/remote_translation.rb b/app/models/remote_translation.rb new file mode 100644 index 000000000..d669f9083 --- /dev/null +++ b/app/models/remote_translation.rb @@ -0,0 +1,21 @@ +class RemoteTranslation < ApplicationRecord + + belongs_to :remote_translatable, polymorphic: true + + validates :remote_translatable_id, presence: true + validates :remote_translatable_type, presence: true + validates :locale, presence: true + + after_create :enqueue_remote_translation + + def enqueue_remote_translation + RemoteTranslations::Caller.new(self).delay.call + end + + def self.remote_translation_enqueued?(remote_translation) + where(remote_translatable_id: remote_translation["remote_translatable_id"], + remote_translatable_type: remote_translation["remote_translatable_type"], + locale: remote_translation["locale"], + error_message: nil).any? + end +end diff --git a/app/models/setting.rb b/app/models/setting.rb index 6e87816dc..a59e38651 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -93,6 +93,8 @@ class Setting < ApplicationRecord "feature.allow_attached_documents": true, "feature.allow_images": true, "feature.help_page": true, + "feature.remote_translations": nil, + "feature.translation_interface": nil, "feature.valuation_comment_notification": true, "homepage.widgets.feeds.debates": true, "homepage.widgets.feeds.processes": true, diff --git a/app/models/widget/feed.rb b/app/models/widget/feed.rb index 2ddd00d62..553d35db6 100644 --- a/app/models/widget/feed.rb +++ b/app/models/widget/feed.rb @@ -34,4 +34,4 @@ class Widget::Feed < ApplicationRecord Legislation::Process.open.published.order("created_at DESC").limit(limit) end -end \ No newline at end of file +end diff --git a/app/views/admin/admin_notifications/_form.html.erb b/app/views/admin/admin_notifications/_form.html.erb index 0048c93a5..d671c2517 100644 --- a/app/views/admin/admin_notifications/_form.html.erb +++ b/app/views/admin/admin_notifications/_form.html.erb @@ -1,19 +1,33 @@ -<%= render "admin/shared/globalize_locales", resource: @admin_notification %> +<%= render "shared/globalize_locales", resource: @admin_notification %> <%= translatable_form_for [:admin, @admin_notification] do |f| %> <%= render "shared/errors", resource: @admin_notification %> - <%= f.select :segment_recipient, options_for_select(user_segments_options, - @admin_notification[:segment_recipient]) %> - <%= f.text_field :link %> +
+
+ <%= f.select :segment_recipient, options_for_select(user_segments_options, + @admin_notification[:segment_recipient]) %> +
+
+ <%= f.text_field :link %> +
+
- <%= f.translatable_fields do |translations_form| %> - <%= translations_form.text_field :title %> - <%= translations_form.text_area :body %> - <% end %> +
+ <%= f.translatable_fields do |translations_form| %> +
+ <%= translations_form.text_field :title %> +
+
+ <%= translations_form.text_area :body %> +
+ <% end %> +
-
- <%= f.submit t("admin.admin_notifications.#{admin_submit_action(@admin_notification)}.submit_button"), - class: "button success" %> +
+
+ <%= f.submit t("admin.admin_notifications.#{admin_submit_action(@admin_notification)}.submit_button"), + class: "button success" %> +
<% end %> diff --git a/app/views/admin/banners/_form.html.erb b/app/views/admin/banners/_form.html.erb index dc01b2918..4bb19e227 100644 --- a/app/views/admin/banners/_form.html.erb +++ b/app/views/admin/banners/_form.html.erb @@ -1,4 +1,4 @@ -<%= render "admin/shared/globalize_locales", resource: @banner %> +<%= render "shared/globalize_locales", resource: @banner %> <%= translatable_form_for [:admin, @banner] do |f| %> diff --git a/app/views/admin/budget_groups/_form.html.erb b/app/views/admin/budget_groups/_form.html.erb index 06a185ae9..bd3cb7d12 100644 --- a/app/views/admin/budget_groups/_form.html.erb +++ b/app/views/admin/budget_groups/_form.html.erb @@ -1,24 +1,34 @@ -<%= render "admin/shared/globalize_locales", resource: @group %> +<%= render "shared/globalize_locales", resource: @group %> -
- <%= translatable_form_for [:admin, @budget, @group], url: path do |f| %> +<%= translatable_form_for [:admin, @budget, @group], url: path do |f| %> - <%= render "shared/errors", resource: @group %> + <%= render "shared/errors", resource: @group %> +
<%= f.translatable_fields do |translations_form| %> - <%= translations_form.text_field :name, - label: t("admin.budget_groups.form.name"), - maxlength: 50, - placeholder: t("admin.budget_groups.form.name") %> +
+ <%= translations_form.text_field :name, + label: t("admin.budget_groups.form.name"), + maxlength: 50, + placeholder: t("admin.budget_groups.form.name") %> +
<% end %> +
- <% if @group.persisted? %> + <% if @group.persisted? %> +
+
<%= f.select :max_votable_headings, (1..@group.headings.count), label: t("admin.budget_groups.max_votable_headings"), placeholder: t("admin.budget_groups.max_votable_headings") %> - <% end %> - - <%= f.submit t("admin.budget_groups.form.#{action}"), class: "button success" %> +
+
<% end %> -
+ +
+
+ <%= f.submit t("admin.budget_groups.form.#{action}"), class: "button success" %> +
+
+<% end %> diff --git a/app/views/admin/budget_headings/_form.html.erb b/app/views/admin/budget_headings/_form.html.erb index 4fe3b75da..45f927ed3 100644 --- a/app/views/admin/budget_headings/_form.html.erb +++ b/app/views/admin/budget_headings/_form.html.erb @@ -1,52 +1,57 @@ -<%= render "admin/shared/globalize_locales", resource: @heading %> +<%= render "shared/globalize_locales", resource: @heading %> -
+<%= translatable_form_for [:admin, @budget, @group, @heading], url: path do |f| %> - <%= translatable_form_for [:admin, @budget, @group, @heading], url: path do |f| %> - - <%= render "shared/errors", resource: @heading %> + <%= render "shared/errors", resource: @heading %> +
<%= f.translatable_fields do |translations_form| %> - <%= translations_form.text_field :name, - label: t("admin.budget_headings.form.name"), - maxlength: 50, - placeholder: t("admin.budget_headings.form.name") %> +
+ <%= translations_form.text_field :name, + label: t("admin.budget_headings.form.name"), + maxlength: 50, + placeholder: t("admin.budget_headings.form.name") %> +
<% end %> +
- <%= f.text_field :price, - label: t("admin.budget_headings.form.amount"), - maxlength: 8, - placeholder: t("admin.budget_headings.form.amount") %> +
+
+ <%= f.text_field :price, + label: t("admin.budget_headings.form.amount"), + maxlength: 8, + placeholder: t("admin.budget_headings.form.amount") %> - <%= f.label :population, t("admin.budget_headings.form.population") %> -

- <%= t("admin.budget_headings.form.population_info") %> -

- <%= f.text_field :population, - label: false, - maxlength: 8, - placeholder: t("admin.budget_headings.form.population"), - data: {toggle_focus: "population-info"}, - aria: {describedby: "budgets-population-help-text"} %> + <%= f.label :population, t("admin.budget_headings.form.population") %> +

+ <%= t("admin.budget_headings.form.population_info") %> +

+ <%= f.text_field :population, + label: false, + maxlength: 8, + placeholder: t("admin.budget_headings.form.population"), + data: {toggle_focus: "population-info"}, + aria: {describedby: "budgets-population-help-text"} %> - <%= f.text_field :latitude, - label: t("admin.budget_headings.form.latitude"), - maxlength: 22, - placeholder: "latitude" %> + <%= f.text_field :latitude, + label: t("admin.budget_headings.form.latitude"), + maxlength: 22, + placeholder: "latitude" %> - <%= f.text_field :longitude, - label: t("admin.budget_headings.form.longitude"), - maxlength: 22, - placeholder: "longitude" %> -

- <%= t("admin.budget_headings.form.coordinates_info") %> -

+ <%= f.text_field :longitude, + label: t("admin.budget_headings.form.longitude"), + maxlength: 22, + placeholder: "longitude" %> +

+ <%= t("admin.budget_headings.form.coordinates_info") %> +

- <%= f.check_box :allow_custom_content, label: t("admin.budget_headings.form.allow_content_block") %> -

- <%= t("admin.budget_headings.form.content_blocks_info") %> -

+ <%= f.check_box :allow_custom_content, label: t("admin.budget_headings.form.allow_content_block") %> +

+ <%= t("admin.budget_headings.form.content_blocks_info") %> +

- <%= f.submit t("admin.budget_headings.form.#{action}"), class: "button success" %> - <% end %> -
+ <%= f.submit t("admin.budget_headings.form.#{action}"), class: "button success" %> +
+
+<% end %> diff --git a/app/views/admin/budget_investments/edit.html.erb b/app/views/admin/budget_investments/edit.html.erb index 23e277dd1..ef6540c9e 100644 --- a/app/views/admin/budget_investments/edit.html.erb +++ b/app/views/admin/budget_investments/edit.html.erb @@ -2,127 +2,134 @@ <%= t("shared.back") %> <% end %> -<%= form_for @investment, - url: admin_budget_budget_investment_path(@budget, @investment) do |f| %> +<%= render "shared/globalize_locales", resource: @investment %> - <% Budget::Investment.filter_params(params).to_h.each do |filter_name, filter_value| %> - <%= hidden_field_tag filter_name, filter_value %> - <% end %> +
+ <%= translatable_form_for @investment, + url: admin_budget_budget_investment_path(@budget, @investment) do |f| %> -
-
- <%= f.text_field :title, - maxlength: Budget::Investment.title_max_length %> -
+ <%= render "shared/errors", resource: @investment %> -
- <%= f.cktext_area :description, - maxlength: Budget::Investment.description_max_length, - ckeditor: { language: I18n.locale } %> -
+ <% Budget::Investment.filter_params(params).to_h.each do |filter_name, filter_value| %> + <%= hidden_field_tag filter_name, filter_value %> + <% end %> -
- <%= f.label :tag_list, t("admin.budget_investments.edit.user_tags") %> - <%= f.text_field :tag_list, - value: @investment.tag_list.sort.join(","), - label: false %> -
+
+ <%= f.translatable_fields do |translations_form| %> +
+ <%= translations_form.text_field :title, + maxlength: Budget::Investment.title_max_length %> +
-
-
- <%= f.text_field :external_url %> +
+ <%= translations_form.cktext_area :description, + maxlength: Budget::Investment.description_max_length, + ckeditor: { language: I18n.locale } %> +
+ <% end %> + +
+ <%= f.label :tag_list, t("admin.budget_investments.edit.user_tags") %> + <%= f.text_field :tag_list, + value: @investment.tag_list.sort.join(","), + label: false %>
-
- <%= f.select :heading_id, budget_heading_select_options(@budget), include_blank: t("admin.budget_investments.edit.select_heading") %> -
-
-
+
+
+ <%= f.text_field :external_url %> +
-
- -
-

<%= t("admin.budget_investments.edit.classification") %>

- -
- <%= f.select(:administrator_id, - @admins.collect{ |a| [a.description_or_name_and_email, a.id ] }, - { include_blank: t("admin.budget_investments.edit.undefined") }) %> +
+ <%= f.select :heading_id, budget_heading_select_options(@budget), include_blank: t("admin.budget_investments.edit.select_heading") %> +
+
-
- <%= f.label :valuation_tag_list, t("admin.budget_investments.edit.tags") %> -
- <% @tags.each do |tag| %> - <%= tag.name %> +
+

<%= t("admin.budget_investments.edit.classification") %>

+ +
+ <%= f.select(:administrator_id, + @admins.collect{ |a| [a.description_or_name_and_email, a.id ] }, + { include_blank: t("admin.budget_investments.edit.undefined") }) %> +
+
+ +
+ <%= f.label :valuation_tag_list, t("admin.budget_investments.edit.tags") %> +
+ <% @tags.each do |tag| %> + <%= tag.name %> + <% end %> +
+ <%= f.text_field :valuation_tag_list, + value: @investment.valuation_tag_list.sort.join(","), + label: false, + placeholder: t("admin.budget_investments.edit.tags_placeholder"), + class: "js-tag-list" %> +
+ +
+ <%= f.label :valuator_ids, t("admin.budget_investments.edit.user_groups") %> +
    + <%= f.collection_check_boxes :valuator_group_ids, @valuator_groups, :id, :name do |group| %> +
  • <%= group.label(title: group.object.name) { group.check_box + truncate(group.object.name, length: 60) } %>
  • + <% end %> +
+
+ +
+
+ <%= f.label :valuator_ids, t("admin.budget_investments.edit.assigned_valuators") %> +
    + <%= f.collection_check_boxes :valuator_ids, @valuators, :id, :email do |b| %> +
  • <%= b.label(title: valuator_label(b.object)) { b.check_box + truncate(b.object.description_or_email, length: 60) } %>
  • + <% end %> +
+
+ +
+
+ <%= f.label :tracker_ids, t("admin.budget_investments.edit.assigned_trackers") %> +
    + <%= f.collection_check_boxes :tracker_ids, @trackers, :id, :email do |b| %> +
  • <%= b.label(title: tracker_label(b.object)) { b.check_box + truncate(b.object.description_or_email, length: 60) } %>
  • + <% end %> +
+
+
+ +
+ <% if @investment.incompatible? || @investment.winner? %> +
+

<%= t("admin.budget_investments.edit.compatibility") %>

+ <%= f.label :incompatible do %> + <%= f.check_box :incompatible, title: t("admin.budget_investments.edit.compatibility"), label: false %> + <%= t("admin.budget_investments.edit.mark_as_incompatible") %> + <% end %> +
+ <% end %> +
+

<%= t("admin.budget_investments.edit.selection") %>

+ <%= f.label :selected do %> + <%= f.check_box :selected, title: t("admin.budget_investments.edit.selection"), label: false %> + <%= t("admin.budget_investments.edit.mark_as_selected") %> <% end %>
- <%= f.text_field :valuation_tag_list, - value: @investment.valuation_tag_list.sort.join(","), - label: false, - placeholder: t("admin.budget_investments.edit.tags_placeholder"), - class: "js-tag-list" %>
+
+ <%= f.text_field :milestone_tag_list, + value: @investment.milestone_tag_list.sort.join(", "), + label: t("admin.budget_investments.edit.milestone_tags") %> +
+ +
- <%= f.label :valuator_ids, t("admin.budget_investments.edit.user_groups") %> -
    - <%= f.collection_check_boxes :valuator_group_ids, @valuator_groups, :id, :name do |group| %> -
  • <%= group.label(title: group.object.name) { group.check_box + truncate(group.object.name, length: 60) } %>
  • - <% end %> -
+ <%= f.submit(class: "button", value: t("admin.budget_investments.edit.submit_button")) %>
- -
-
- <%= f.label :valuator_ids, t("admin.budget_investments.edit.assigned_valuators") %> -
    - <%= f.collection_check_boxes :valuator_ids, @valuators, :id, :email do |b| %> -
  • <%= b.label(title: valuator_label(b.object)) { b.check_box + truncate(b.object.description_or_email, length: 60) } %>
  • - <% end %> -
-
- -
-
- <%= f.label :tracker_ids, t("admin.budget_investments.edit.assigned_trackers") %> -
    - <%= f.collection_check_boxes :tracker_ids, @trackers, :id, :email do |b| %> -
  • <%= b.label(title: tracker_label(b.object)) { b.check_box + truncate(b.object.description_or_email, length: 60) } %>
  • - <% end %> -
-
-
- -
- <% if @investment.incompatible? || @investment.winner? %> -
-

<%= t("admin.budget_investments.edit.compatibility") %>

- <%= f.label :incompatible do %> - <%= f.check_box :incompatible, title: t("admin.budget_investments.edit.compatibility"), label: false %> - <%= t("admin.budget_investments.edit.mark_as_incompatible") %> - <% end %> -
- <% end %> -
-

<%= t("admin.budget_investments.edit.selection") %>

- <%= f.label :selected do %> - <%= f.check_box :selected, title: t("admin.budget_investments.edit.selection"), label: false %> - <%= t("admin.budget_investments.edit.mark_as_selected") %> - <% end %> -
-
- -
- <%= f.text_field :milestone_tag_list, - value: @investment.milestone_tag_list.sort.join(", "), - label: t("admin.budget_investments.edit.milestone_tags") %> -
- - -
- <%= f.submit(class: "button", value: t("admin.budget_investments.edit.submit_button")) %> -
-<% end %> + <% end %> +
diff --git a/app/views/admin/budget_phases/_form.html.erb b/app/views/admin/budget_phases/_form.html.erb index 05b4139be..4bb746219 100644 --- a/app/views/admin/budget_phases/_form.html.erb +++ b/app/views/admin/budget_phases/_form.html.erb @@ -1,65 +1,74 @@ -<%= render "admin/shared/globalize_locales", resource: @phase %> +<%= render "shared/globalize_locales", resource: @phase %> <%= translatable_form_for [:admin, @phase.budget, @phase] do |f| %> <%= render "shared/errors", resource: @phase %> -
- <%= f.label :starts_at, t("admin.budget_phases.edit.start_date") %> - <%= f.text_field :starts_at, - value: format_date_for_calendar_form(@phase.starts_at), - class: "js-calendar-full", - id: "start_date", - label: false %> -
-
- <%= f.label :ends_at, t("admin.budget_phases.edit.end_date") %> - <%= f.text_field :ends_at, - value: format_date_for_calendar_form(@phase.ends_at), - class: "js-calendar-full", - id: "end_date", - label: false %> +
+
+ <%= f.label :starts_at, t("admin.budget_phases.edit.start_date") %> + <%= f.text_field :starts_at, + value: format_date_for_calendar_form(@phase.starts_at), + class: "js-calendar-full", + id: "start_date", + label: false %> +
+
+ <%= f.label :ends_at, t("admin.budget_phases.edit.end_date") %> + <%= f.text_field :ends_at, + value: format_date_for_calendar_form(@phase.ends_at), + class: "js-calendar-full", + id: "end_date", + label: false %> +
-
+
<%= f.translatable_fields do |translations_form| %> +
+ <%= f.label :description, t("admin.budget_phases.edit.description") %> - <%= f.label :description, t("admin.budget_phases.edit.description") %> + + <%= t("admin.budget_phases.edit.description_help_text") %> + - - <%= t("admin.budget_phases.edit.description_help_text") %> - - -
- <%= translations_form.cktext_area :description, - maxlength: Budget::Phase::DESCRIPTION_MAX_LENGTH, - label: false %> +
+ <%= translations_form.cktext_area :description, + maxlength: Budget::Phase::DESCRIPTION_MAX_LENGTH, + label: false %> +
- <%= f.label :summary, t("admin.budget_phases.edit.summary") %> +
+ <%= f.label :summary, t("admin.budget_phases.edit.summary") %> - - <%= t("admin.budget_phases.edit.summary_help_text") %> - + + <%= t("admin.budget_phases.edit.summary_help_text") %> + -
- <%= translations_form.cktext_area :summary, - maxlength: Budget::Phase::SUMMARY_MAX_LENGTH, - label: false%> +
+ <%= translations_form.cktext_area :summary, + maxlength: Budget::Phase::SUMMARY_MAX_LENGTH, + label: false %> +
<% end %>
-
- <%= f.check_box :enabled, label: t("admin.budget_phases.edit.enabled") %> +
+
+ <%= f.check_box :enabled, label: t("admin.budget_phases.edit.enabled") %> - - <%= t("admin.budget_phases.edit.enabled_help_text") %> - + + <%= t("admin.budget_phases.edit.enabled_help_text") %> + +
-
- <%= f.submit t("admin.budget_phases.edit.save_changes"), class: "button success expanded" %> +
+
+ <%= f.submit t("admin.budget_phases.edit.save_changes"), class: "button success expanded" %> +
<% end %> diff --git a/app/views/admin/budget_phases/edit.html.erb b/app/views/admin/budget_phases/edit.html.erb index 7161abc88..9cf9a6745 100644 --- a/app/views/admin/budget_phases/edit.html.erb +++ b/app/views/admin/budget_phases/edit.html.erb @@ -1,7 +1,9 @@ <%= back_link_to edit_admin_budget_path(@phase.budget) %> -
-

<%= t("admin.budgets.edit.title") %> - <%= t("budgets.phase.#{@phase.kind}") %>

+
+
+

<%= t("admin.budgets.edit.title") %> - <%= t("budgets.phase.#{@phase.kind}") %>

+
<%= render "/admin/budget_phases/form" %> diff --git a/app/views/admin/budgets/_form.html.erb b/app/views/admin/budgets/_form.html.erb index b552821e1..e8337e551 100644 --- a/app/views/admin/budgets/_form.html.erb +++ b/app/views/admin/budgets/_form.html.erb @@ -1,4 +1,4 @@ -<%= render "admin/shared/globalize_locales", resource: @budget %> +<%= render "shared/globalize_locales", resource: @budget %> <%= translatable_form_for [:admin, @budget] do |f| %> @@ -6,16 +6,18 @@ <%= render "shared/errors", resource: @budget %> -
+
<%= f.translatable_fields do |translations_form| %> - <%= translations_form.text_field :name, - label: t("activerecord.attributes.budget.name"), - maxlength: Budget.title_max_length, - placeholder: t("activerecord.attributes.budget.name") %> +
+ <%= translations_form.text_field :name, + label: t("activerecord.attributes.budget.name"), + maxlength: Budget.title_max_length, + placeholder: t("activerecord.attributes.budget.name") %> +
<% end %>
-
+
<%= f.select :phase, budget_phases_select_options %>
@@ -58,76 +60,80 @@
<% if @budget.phases.present? %> -
- - - - - - - - - +
+
+
<%= t("admin.budgets.edit.phase") %><%= t("admin.budgets.edit.dates") %><%= t("admin.budgets.edit.enabled") %><%= t("admin.budgets.edit.actions") %>
+ + + + + + + + - <% @budget.phases.order(:id).each do |phase| %> - - - - - - - <% end %> -
<%= t("admin.budgets.edit.phase") %><%= t("admin.budgets.edit.dates") %><%= t("admin.budgets.edit.enabled") %><%= t("admin.budgets.edit.actions") %>
- <%= t("budgets.phase.#{phase.kind}") %> - <% if @budget.current_phase == phase %> - <%= t("admin.budgets.edit.active") %> - <% end %> - - <% if phase.starts_at.present? || phase.ends_at.present? %> - <%= l(phase.starts_at.to_date) if phase.starts_at.present? %> - - - <%= l(phase.ends_at.to_date) if phase.ends_at.present? %> - <% else %> - <%= t("admin.budgets.edit.blank_dates") %> - <% end %> - - "> - - <%= link_to t("admin.budgets.edit.edit_phase"), - edit_admin_budget_budget_phase_path(@budget, phase), - method: :get, class: "button hollow expanded" %> -
+ <% @budget.phases.order(:id).each do |phase| %> + + + <%= t("budgets.phase.#{phase.kind}") %> + <% if @budget.current_phase == phase %> + <%= t("admin.budgets.edit.active") %> + <% end %> + + + <% if phase.starts_at.present? || phase.ends_at.present? %> + <%= l(phase.starts_at.to_date) if phase.starts_at.present? %> + - + <%= l(phase.ends_at.to_date) if phase.ends_at.present? %> + <% else %> + <%= t("admin.budgets.edit.blank_dates") %> + <% end %> + + + "> + + + <%= link_to t("admin.budgets.edit.edit_phase"), + edit_admin_budget_budget_phase_path(@budget, phase), + method: :get, class: "button hollow expanded" %> + + + <% end %> + +
<% end %> -
- <%= render "admin/shared/show_results_fields", form: f %> -
- -
-
- <%= f.submit nil, class: "button success" %> +
+
+ <%= render "admin/shared/show_results_fields", form: f %>
-
- <% if display_calculate_winners_button?(@budget) %> - <%= link_to calculate_winner_button_text(@budget), - calculate_winners_admin_budget_path(@budget), - method: :put, - class: "button hollow" %> - <% end %> +
+
+ <%= f.submit nil, class: "button success" %> +
- <% if @budget.has_winning_investments? %> - <%= link_to t("budgets.show.see_results"), - budget_results_path(@budget), - class: "button hollow margin-left" %> - <% end %> - <% if @budget.persisted? %> - <%= link_to t("admin.budgets.edit.delete"), - admin_budget_path(@budget), - method: :delete, - class: "delete float-right margin-left" %> - <% end %> +
+ <% if display_calculate_winners_button?(@budget) %> + <%= link_to calculate_winner_button_text(@budget), + calculate_winners_admin_budget_path(@budget), + method: :put, + class: "button hollow" %> + <% end %> + + <% if @budget.has_winning_investments? %> + <%= link_to t("budgets.show.see_results"), + budget_results_path(@budget), + class: "button hollow margin-left" %> + <% end %> + <% if @budget.persisted? %> + <%= link_to t("admin.budgets.edit.delete"), + admin_budget_path(@budget), + method: :delete, + class: "delete float-right margin-left" %> + <% end %> +
<% end %> diff --git a/app/views/admin/budgets/edit.html.erb b/app/views/admin/budgets/edit.html.erb index 508279796..2ccbba53a 100644 --- a/app/views/admin/budgets/edit.html.erb +++ b/app/views/admin/budgets/edit.html.erb @@ -1,7 +1,9 @@ <%= back_link_to admin_budgets_path %> -
-

<%= t("admin.budgets.edit.title") %>

+
+
+

<%= t("admin.budgets.edit.title") %>

+
<%= render "/admin/budgets/form" %> diff --git a/app/views/admin/budgets/new.html.erb b/app/views/admin/budgets/new.html.erb index aca444559..a9d08340c 100644 --- a/app/views/admin/budgets/new.html.erb +++ b/app/views/admin/budgets/new.html.erb @@ -1,5 +1,3 @@ -
-

<%= t("admin.budgets.new.title") %>

-
+

<%= t("admin.budgets.new.title") %>

<%= render "/admin/budgets/form" %> diff --git a/app/views/admin/legislation/draft_versions/_form.html.erb b/app/views/admin/legislation/draft_versions/_form.html.erb index 754b420ca..3ef7247b4 100644 --- a/app/views/admin/legislation/draft_versions/_form.html.erb +++ b/app/views/admin/legislation/draft_versions/_form.html.erb @@ -1,4 +1,4 @@ -<%= render "admin/shared/globalize_locales", resource: @draft_version %> +<%= render "shared/globalize_locales", resource: @draft_version %> <%= translatable_form_for [:admin, @process, @draft_version], url: url, html: {data: {watch_changes: true}} do |f| %> @@ -15,73 +15,77 @@
<% end %> - <%= f.translatable_fields do |translations_form| %> -
- <%= translations_form.text_field :title, - placeholder: t("admin.legislation.draft_versions.form.title_placeholder") %> -
+
+ <%= f.translatable_fields do |translations_form| %> +
+ <%= translations_form.text_field :title, + placeholder: t("admin.legislation.draft_versions.form.title_placeholder") %> +
-
- <%= translations_form.text_area :changelog, - hint: t("admin.legislation.draft_versions.form.use_markdown"), - rows: 5, - placeholder: t("admin.legislation.draft_versions.form.changelog_placeholder") %> -
+
+ <%= translations_form.text_area :changelog, + hint: t("admin.legislation.draft_versions.form.use_markdown"), + rows: 5, + placeholder: t("admin.legislation.draft_versions.form.changelog_placeholder") %> +
-
- <%= translations_form.label :body, nil, hint: t("admin.legislation.draft_versions.form.use_markdown") %> -
+
+ <%= translations_form.label :body, nil, hint: t("admin.legislation.draft_versions.form.use_markdown") %> +
-
-
-
- <%= t("admin.legislation.draft_versions.form.title_html", - draft_version_title: @draft_version.title, - process_title: @process.title ) %> +
+
+
+ <%= t("admin.legislation.draft_versions.form.title_html", + draft_version_title: @draft_version.title, + process_title: @process.title ) %> +
+ +
+ <%= f.submit(class: "button", value: t("admin.legislation.draft_versions.#{admin_submit_action(@draft_version)}.submit_button")) %> +
+ + <%= link_to "#", class: "fullscreen-toggle" do %> + " + data-open-text="<%= t("admin.legislation.draft_versions.form.close_text_editor") %>"> + <%= t("admin.legislation.draft_versions.form.launch_text_editor") %> + + + <% end %>
-
- <%= f.submit(class: "button", value: t("admin.legislation.draft_versions.#{admin_submit_action(@draft_version)}.submit_button")) %> +
+ <%= translations_form.text_area :body, + label: false, + rows: 10, + placeholder: t("admin.legislation.draft_versions.form.body_placeholder") %>
- <%= link_to "#", class: "fullscreen-toggle" do %> - " - data-open-text="<%= t("admin.legislation.draft_versions.form.close_text_editor")%>"> - <%= t("admin.legislation.draft_versions.form.launch_text_editor")%> - - - <% end %> +
+
- -
- <%= translations_form.text_area :body, - label: false, - rows: 10, - placeholder: t("admin.legislation.draft_versions.form.body_placeholder") %> -
- -
-
-
- <% end %> - -
- <%= f.label :status %> - <% ::Legislation::DraftVersion::VALID_STATUSES.each do |status| %> - <%= f.radio_button :status, status, label: false %> - <%= f.label "status_#{status}", t("admin.legislation.draft_versions.statuses.#{status}") %> - <%= t("admin.legislation.draft_versions.form.hints.status.#{status}") %> -
<% end %>
-
- <%= f.label :final_version %> - <%= f.check_box :final_version, label: false %> - <%= t("admin.legislation.draft_versions.form.hints.final_version") %> -
+
+
+ <%= f.label :status %> + <% ::Legislation::DraftVersion::VALID_STATUSES.each do |status| %> + <%= f.radio_button :status, status, label: false %> + <%= f.label "status_#{status}", t("admin.legislation.draft_versions.statuses.#{status}") %> + <%= t("admin.legislation.draft_versions.form.hints.status.#{status}") %> +
+ <% end %> +
-
- <%= f.submit(class: "button success expanded", value: t("admin.legislation.draft_versions.#{admin_submit_action(@draft_version)}.submit_button")) %> +
+ <%= f.label :final_version %> + <%= f.check_box :final_version, label: false %> + <%= t("admin.legislation.draft_versions.form.hints.final_version") %> +
+ +
+ <%= f.submit(class: "button success expanded", value: t("admin.legislation.draft_versions.#{admin_submit_action(@draft_version)}.submit_button")) %> +
<% end %> diff --git a/app/views/admin/legislation/draft_versions/new.html.erb b/app/views/admin/legislation/draft_versions/new.html.erb index 90b2c634f..fd3498afa 100644 --- a/app/views/admin/legislation/draft_versions/new.html.erb +++ b/app/views/admin/legislation/draft_versions/new.html.erb @@ -11,9 +11,7 @@ <%= render "admin/legislation/processes/subnav", process: @process, active: "draft_versions" %> -
-

<%= t("admin.legislation.draft_versions.new.title") %>

-
+

<%= t("admin.legislation.draft_versions.new.title") %>

<%= render "form", url: admin_legislation_process_draft_versions_path(@process) %>
diff --git a/app/views/admin/legislation/homepages/_form.html.erb b/app/views/admin/legislation/homepages/_form.html.erb index d5e276aa2..4ce79ab30 100644 --- a/app/views/admin/legislation/homepages/_form.html.erb +++ b/app/views/admin/legislation/homepages/_form.html.erb @@ -1,28 +1,34 @@ -<%= render "admin/shared/globalize_tabs", +<%= render "shared/globalize_locales", resource: @process, - display_style: lambda { |locale| enable_translation_style(@process, locale) } %> + display_style: lambda { |locale| enable_translation_style(@process, locale) }, + manage_languages: false %> <%= translatable_form_for [:admin, @process], url: url, html: {data: {watch_changes: true}} do |f| %> <%= render "shared/errors", resource: @process %> - -
- <%= f.check_box :homepage_enabled, label: t("admin.legislation.processes.form.homepage_enabled") %> +
+
+ <%= f.check_box :homepage_enabled, label: t("admin.legislation.processes.form.homepage_enabled") %> +
- <%= f.translatable_fields do |translations_form| %> -
-
- <%= translations_form.cktext_area :homepage, - language: I18n.locale, - label: t("admin.legislation.processes.form.homepage"), - ckeditor: { height: 500, toolbar: "admin" }, - hint: t("admin.legislation.processes.form.homepage_description") %> +
+ <%= f.translatable_fields do |translations_form| %> +
+
+ <%= translations_form.cktext_area :homepage, + language: I18n.locale, + label: t("admin.legislation.processes.form.homepage"), + ckeditor: { height: 500, toolbar: "admin" }, + hint: t("admin.legislation.processes.form.homepage_description") %> +
-
- <% end %> + <% end %> +
-
- <%= f.submit(class: "button success expanded", value: t("admin.legislation.processes.#{admin_submit_action(@process)}.submit_button")) %> +
+
+ <%= f.submit(class: "button success expanded", value: t("admin.legislation.processes.#{admin_submit_action(@process)}.submit_button")) %> +
<% end %> diff --git a/app/views/admin/legislation/milestones/_summary_form.html.erb b/app/views/admin/legislation/milestones/_summary_form.html.erb index 952926572..3c4297049 100644 --- a/app/views/admin/legislation/milestones/_summary_form.html.erb +++ b/app/views/admin/legislation/milestones/_summary_form.html.erb @@ -1,13 +1,20 @@ -<%= render "admin/shared/globalize_tabs", +<%= render "shared/globalize_locales", resource: @process, - display_style: lambda { |locale| enable_translation_style(@process, locale) } %> + display_style: lambda { |locale| enable_translation_style(@process, locale) }, + manage_languages: false %> <%= translatable_form_for [:admin, @process] do |f| %> - <%= f.translatable_fields do |translations_form| %> -
- <%= translations_form.cktext_area :milestones_summary, ckeditor: { language: I18n.locale } %> -
- <% end %> +
+ <%= f.translatable_fields do |translations_form| %> +
+ <%= translations_form.cktext_area :milestones_summary, ckeditor: { language: I18n.locale } %> +
+ <% end %> +
- <%= f.submit class: "button success" %> +
+
+ <%= f.submit class: "button success" %> +
+
<% end %> diff --git a/app/views/admin/legislation/processes/_form.html.erb b/app/views/admin/legislation/processes/_form.html.erb index eb9b1d6d2..d95f65598 100644 --- a/app/views/admin/legislation/processes/_form.html.erb +++ b/app/views/admin/legislation/processes/_form.html.erb @@ -1,256 +1,261 @@ -<%= render "admin/shared/globalize_locales", resource: @process %> +<%= render "shared/globalize_locales", resource: @process %> <%= translatable_form_for [:admin, @process], html: {data: {watch_changes: true}} do |f| %> <% if @process.errors.any? %> -
- +
+ - - <%= @process.errors.count %> - <%= t("admin.legislation.processes.errors.form.error", count: @process.errors.count) %> - -
+ + <%= @process.errors.count %> + <%= t("admin.legislation.processes.errors.form.error", count: @process.errors.count) %> + +
<% end %> +
+
+ +

<%= t("admin.legislation.processes.form.draft_phase_description") %>

+
-
- -

<%= t("admin.legislation.processes.form.draft_phase_description") %>

-
+
+ <%= f.text_field :draft_start_date, + value: format_date_for_calendar_form(@process.draft_start_date), + class: "js-calendar-full", + id: "draft_start_date" %> +
-
- <%= f.text_field :draft_start_date, - value: format_date_for_calendar_form(@process.draft_start_date), - class: "js-calendar-full", - id: "draft_start_date" %> -
+
+ <%= f.text_field :draft_end_date, + value: format_date_for_calendar_form(@process.draft_end_date), + class: "js-calendar-full", + id: "draft_end_date" %> +
+
+ <%= f.check_box :draft_phase_enabled, checked: @process.draft_phase.enabled?, label: t("admin.legislation.processes.form.enabled") %> +
-
- <%= f.text_field :draft_end_date, - value: format_date_for_calendar_form(@process.draft_end_date), - class: "js-calendar-full", - id: "draft_end_date" %> -
-
- <%= f.check_box :draft_phase_enabled, checked: @process.draft_phase.enabled?, label: t("admin.legislation.processes.form.enabled") %> -
+
+
+
-
-
-
+
+ +
-
- -
+
+ <%= f.text_field :start_date, + value: format_date_for_calendar_form(@process.start_date), + class: "js-calendar-full", + id: "start_date" %> +
-
- <%= f.text_field :start_date, - value: format_date_for_calendar_form(@process.start_date), - class: "js-calendar-full", - id: "start_date" %> -
+
+ <%= f.text_field :end_date, + value: format_date_for_calendar_form(@process.end_date), + class: "js-calendar-full", + id: "end_date" %> +
+
+ <%= f.check_box :published, checked: @process.published?, label: t("admin.legislation.processes.form.enabled") %> +
-
- <%= f.text_field :end_date, - value: format_date_for_calendar_form(@process.end_date), - class: "js-calendar-full", - id: "end_date" %> -
-
- <%= f.check_box :published, checked: @process.published?, label: t("admin.legislation.processes.form.enabled") %> -
+
+
+
-
-
-
+
+ +
-
- -
+
+ <%= f.text_field :debate_start_date, + value: format_date_for_calendar_form(@process.debate_start_date), + class: "js-calendar-full", + id: "debate_start_date" %> +
-
- <%= f.text_field :debate_start_date, - value: format_date_for_calendar_form(@process.debate_start_date), - class: "js-calendar-full", - id: "debate_start_date" %> -
+
+ <%= f.text_field :debate_end_date, + value: format_date_for_calendar_form(@process.debate_end_date), + class: "js-calendar-full", + id: "debate_end_date" %> +
+
+ <%= f.check_box :debate_phase_enabled, checked: @process.debate_phase.enabled?, label: t("admin.legislation.processes.form.enabled") %> +
-
- <%= f.text_field :debate_end_date, - value: format_date_for_calendar_form(@process.debate_end_date), - class: "js-calendar-full", - id: "debate_end_date" %> -
-
- <%= f.check_box :debate_phase_enabled, checked: @process.debate_phase.enabled?, label: t("admin.legislation.processes.form.enabled") %> -
+
+
+
-
-
-
+
+ +
-
- -
+
+ <%= f.text_field :proposals_phase_start_date, + value: format_date_for_calendar_form(@process.proposals_phase_start_date), + class: "js-calendar-full", + id: "proposals_phase_start_date" %> +
-
- <%= f.text_field :proposals_phase_start_date, - value: format_date_for_calendar_form(@process.proposals_phase_start_date), - class: "js-calendar-full", - id: "proposals_phase_start_date" %> -
+
+ <%= f.text_field :proposals_phase_end_date, + value: format_date_for_calendar_form(@process.proposals_phase_end_date), + class: "js-calendar-full", + id: "proposals_phase_end_date" %> +
+
+ <%= f.check_box :proposals_phase_enabled, checked: @process.proposals_phase.enabled?, label: t("admin.legislation.processes.form.enabled") %> +
-
- <%= f.text_field :proposals_phase_end_date, - value: format_date_for_calendar_form(@process.proposals_phase_end_date), - class: "js-calendar-full", - id: "proposals_phase_end_date" %> -
-
- <%= f.check_box :proposals_phase_enabled, checked: @process.proposals_phase.enabled?, label: t("admin.legislation.processes.form.enabled") %> -
+
+
+
-
-
-
+
+ +
-
- -
+
+ <%= f.text_field :allegations_start_date, + value: format_date_for_calendar_form(@process.allegations_start_date), + class: "js-calendar-full", + id: "allegations_start_date" %> +
-
- <%= f.text_field :allegations_start_date, - value: format_date_for_calendar_form(@process.allegations_start_date), - class: "js-calendar-full", - id: "allegations_start_date" %> -
+
+ <%= f.text_field :allegations_end_date, + value: format_date_for_calendar_form(@process.allegations_end_date), + class: "js-calendar-full", + id: "allegations_end_date" %> +
+
+ <%= f.check_box :allegations_phase_enabled, checked: @process.allegations_phase.enabled?, label: t("admin.legislation.processes.form.enabled") %> +
-
- <%= f.text_field :allegations_end_date, - value: format_date_for_calendar_form(@process.allegations_end_date), - class: "js-calendar-full", - id: "allegations_end_date" %> -
-
- <%= f.check_box :allegations_phase_enabled, checked: @process.allegations_phase.enabled?, label: t("admin.legislation.processes.form.enabled") %> -
+
+
+
-
-
-
+
+ <%= f.text_field :draft_publication_date, + value: format_date_for_calendar_form(@process.draft_publication_date), + class: "js-calendar-full", + id: "draft_publication_date" %> +
+
+ <%= f.check_box :draft_publication_enabled, checked: @process.draft_publication.enabled?, label: t("admin.legislation.processes.form.enabled") %> +
-
- <%= f.text_field :draft_publication_date, - value: format_date_for_calendar_form(@process.draft_publication_date), - class: "js-calendar-full", - id: "draft_publication_date" %> -
-
- <%= f.check_box :draft_publication_enabled, checked: @process.draft_publication.enabled?, label: t("admin.legislation.processes.form.enabled") %> -
+
+
+
-
-
-
+
+ <%= f.text_field :result_publication_date, + value: format_date_for_calendar_form(@process.result_publication_date), + class: "js-calendar-full", + id: "result_publication_date" %> +
+
+ <%= f.check_box :result_publication_enabled, checked: @process.result_publication.enabled?, label: t("admin.legislation.processes.form.enabled") %> +
-
- <%= f.text_field :result_publication_date, - value: format_date_for_calendar_form(@process.result_publication_date), - class: "js-calendar-full", - id: "result_publication_date" %> -
-
- <%= f.check_box :result_publication_enabled, checked: @process.result_publication.enabled?, label: t("admin.legislation.processes.form.enabled") %> -
+
+
+
-
-
-
+
+ <%= render "documents/nested_documents", documentable: @process, f: f %> +
-
- <%= render "documents/nested_documents", documentable: @process, f: f %> -
+
+
+
-
-
-
+
+ <%= render "images/nested_image", imageable: @process, f: f %> +
-
- <%= render "images/nested_image", imageable: @process, f: f %> -
+
+
+
-
-
-
+
+

<%= t("admin.legislation.processes.form.banner_title") %>

+
-
-

<%= t("admin.legislation.processes.form.banner_title") %>

-
- -
- <%= f.label :background_color, nil, for: "background_color_input" %> -

<%= t("admin.shared.color_help") %>

-
-
- <%= f.text_field :background_color, label: false, type: :color, - value: bg_color_or_default %> -
-
- <%= f.text_field :background_color, label: false, id: "background_color_input" %> +
+ <%= f.label :background_color, nil, for: "background_color_input" %> +

<%= t("admin.shared.color_help") %>

+
+
+ <%= f.text_field :background_color, label: false, type: :color, + value: bg_color_or_default %> +
+
+ <%= f.text_field :background_color, label: false, id: "background_color_input" %> +
-
-
- <%= f.label :font_color, nil, for: "font_color_input" %> -

<%= t("admin.shared.color_help") %>

-
-
- <%= f.text_field :font_color, label: false, type: :color, value: font_color_or_default %> -
-
- <%= f.text_field :font_color, label: false, id: "font_color_input" %> +
+ <%= f.label :font_color, nil, for: "font_color_input" %> +

<%= t("admin.shared.color_help") %>

+
+
+ <%= f.text_field :font_color, label: false, type: :color, value: font_color_or_default %> +
+
+ <%= f.text_field :font_color, label: false, id: "font_color_input" %> +
+ +
+
+
-
-
+
+ <%= f.translatable_fields do |translations_form| %> +
+ <%= translations_form.text_field :title, + placeholder: t("admin.legislation.processes.form.title_placeholder") %> +
+ +
+ <%= translations_form.text_area :summary, + rows: 2, + placeholder: t("admin.legislation.processes.form.summary_placeholder"), + hint: t("admin.legislation.processes.form.use_markdown") %> +
+ +
+ <%= translations_form.text_area :description, + rows: 5, + placeholder: t("admin.legislation.processes.form.description_placeholder"), + hint: t("admin.legislation.processes.form.use_markdown") %> +
+ +
+ <%= translations_form.text_area :additional_info, + rows: 10, + placeholder: t("admin.legislation.processes.form.additional_info_placeholder"), + hint: t("admin.legislation.processes.form.use_markdown") %> +
+ <% end %>
- <%= f.translatable_fields do |translations_form| %> -
- <%= translations_form.text_field :title, - placeholder: t("admin.legislation.processes.form.title_placeholder") %> +
+
+ <%= f.submit(class: "button success expanded", value: t("admin.legislation.processes.#{admin_submit_action(@process)}.submit_button")) %>
- -
- <%= translations_form.text_area :summary, - rows: 2, - placeholder: t("admin.legislation.processes.form.summary_placeholder"), - hint: t("admin.legislation.processes.form.use_markdown") %> -
- -
- <%= translations_form.text_area :description, - rows: 5, - placeholder: t("admin.legislation.processes.form.description_placeholder"), - hint: t("admin.legislation.processes.form.use_markdown") %> -
- -
- <%= translations_form.text_area :additional_info, - rows: 10, - placeholder: t("admin.legislation.processes.form.additional_info_placeholder"), - hint: t("admin.legislation.processes.form.use_markdown") %> -
- <% end %> - -
- <%= f.submit(class: "button success expanded", value: t("admin.legislation.processes.#{admin_submit_action(@process)}.submit_button")) %>
<% end %> diff --git a/app/views/admin/legislation/questions/_form.html.erb b/app/views/admin/legislation/questions/_form.html.erb index daccb3dfe..22964c95a 100644 --- a/app/views/admin/legislation/questions/_form.html.erb +++ b/app/views/admin/legislation/questions/_form.html.erb @@ -1,4 +1,4 @@ -<%= render "admin/shared/globalize_locales", resource: @question %> +<%= render "shared/globalize_locales", resource: @question %> <%= translatable_form_for [:admin, @process, @question], url: url, html: {data: {watch_changes: true}} do |f| %> @@ -17,33 +17,37 @@
<% end %> - <%= f.translatable_fields do |translations_form| %> -
- <%= translations_form.text_area :title, - rows: 5, - placeholder: t("admin.legislation.questions.form.title_placeholder"), - label: t("admin.legislation.questions.form.title") %> -
- <% end %> - -
- <%= f.label :question_options, t("admin.legislation.questions.form.question_options") %> +
+ <%= f.translatable_fields do |translations_form| %> +
+ <%= translations_form.text_area :title, + rows: 5, + placeholder: t("admin.legislation.questions.form.title_placeholder"), + label: t("admin.legislation.questions.form.title") %> +
+ <% end %>
-
- <%= f.fields_for :question_options do |ff| %> - <%= render "question_option_fields", f: ff %> - <% end %> +
+
+ <%= f.label :question_options, t("admin.legislation.questions.form.question_options") %> +
-
-
- <%= link_to_add_association t("admin.legislation.questions.form.add_option"), - f, :question_options, class: "button hollow" %> +
+ <%= f.fields_for :question_options do |ff| %> + <%= render "question_option_fields", f: ff %> + <% end %> + +
+
+ <%= link_to_add_association t("admin.legislation.questions.form.add_option"), + f, :question_options, class: "button hollow" %> +
-
-
- <%= f.submit(class: "button success expanded", value: t("admin.legislation.questions.#{admin_submit_action(@question)}.submit_button")) %> +
+ <%= f.submit(class: "button success expanded", value: t("admin.legislation.questions.#{admin_submit_action(@question)}.submit_button")) %> +
<% end %> diff --git a/app/views/admin/legislation/questions/edit.html.erb b/app/views/admin/legislation/questions/edit.html.erb index 6db283eba..3151efa90 100644 --- a/app/views/admin/legislation/questions/edit.html.erb +++ b/app/views/admin/legislation/questions/edit.html.erb @@ -10,13 +10,15 @@ <%= render "admin/legislation/processes/subnav", process: @process, active: "questions" %> -
-

<%= t("admin.legislation.questions.edit.title", question_title: @question.title) %>

+
+
+

<%= t("admin.legislation.questions.edit.title", question_title: @question.title) %>

-
- <%= link_to t("admin.legislation.questions.index.delete"), admin_legislation_process_question_path(@process, @question), - method: :delete, - class: "button hollow alert" %> +
+ <%= link_to t("admin.legislation.questions.index.delete"), admin_legislation_process_question_path(@process, @question), + method: :delete, + class: "button hollow alert" %> +
diff --git a/app/views/admin/legislation/questions/new.html.erb b/app/views/admin/legislation/questions/new.html.erb index 6b9c54519..da50c0e0a 100644 --- a/app/views/admin/legislation/questions/new.html.erb +++ b/app/views/admin/legislation/questions/new.html.erb @@ -9,9 +9,10 @@

<%= @process.title %>

<%= render "admin/legislation/processes/subnav", process: @process, active: "questions" %> - -
-

<%= t("admin.legislation.questions.new.title") %>

+
+
+

<%= t("admin.legislation.questions.new.title") %>

+
<%= render "form", url: admin_legislation_process_questions_path(@process) %> diff --git a/app/views/admin/poll/active_polls/_form.html.erb b/app/views/admin/poll/active_polls/_form.html.erb index 4e7fc766e..be6bd8fb9 100644 --- a/app/views/admin/poll/active_polls/_form.html.erb +++ b/app/views/admin/poll/active_polls/_form.html.erb @@ -1,20 +1,24 @@ -<%= render "admin/shared/globalize_locales", resource: @active_poll %> +<%= render "shared/globalize_locales", resource: @active_poll %> <%= translatable_form_for(@active_poll, url: form_url) do |f| %> <%= render "shared/errors", resource: @active_poll %> - <%= f.translatable_fields do |translations_form| %> -
- <%= t("admin.active_polls.form.description.help_text") %> - <%= translations_form.cktext_area :description, - maxlength: ActivePoll.description_max_length, - label: t("admin.active_polls.form.description.text") %> -
- <% end %> +
+ <%= f.translatable_fields do |translations_form| %> +
+ <%= t("admin.active_polls.form.description.help_text") %> + <%= translations_form.cktext_area :description, + maxlength: ActivePoll.description_max_length, + label: t("admin.active_polls.form.description.text") %> +
+ <% end %> +
-
- <%= f.submit(class: "button success", value: t("shared.save")) %> +
+
+ <%= f.submit(class: "button success", value: t("shared.save")) %> +
<% end %> diff --git a/app/views/admin/poll/polls/_form.html.erb b/app/views/admin/poll/polls/_form.html.erb index 98c1d8d2f..75b28dc40 100644 --- a/app/views/admin/poll/polls/_form.html.erb +++ b/app/views/admin/poll/polls/_form.html.erb @@ -1,44 +1,49 @@ -<%= render "admin/shared/globalize_locales", resource: @poll %> +<%= render "shared/globalize_locales", resource: @poll %> <%= translatable_form_for [:admin, @poll] do |f| %> <%= render "shared/errors", resource: @poll %> -
-
- <%= f.text_field :starts_at, - value: @poll.starts_at.present? ? l(@poll.starts_at.to_date) : nil, - class: "js-calendar-full" %> -
+
+
+
+ <%= f.text_field :starts_at, + value: @poll.starts_at.present? ? l(@poll.starts_at.to_date) : nil, + class: "js-calendar-full" %> +
-
- <%= f.text_field :ends_at, - value: @poll.ends_at.present? ? l(@poll.ends_at.to_date) : nil, - class: "js-calendar-full" %> +
+ <%= f.text_field :ends_at, + value: @poll.ends_at.present? ? l(@poll.ends_at.to_date) : nil, + class: "js-calendar-full" %> +
+
+ <%= f.translatable_fields do |translations_form| %> +
+ <%= translations_form.text_field :name %> +
- <%= f.translatable_fields do |translations_form| %> -
- <%= translations_form.text_field :name %> -
+
+ <%= translations_form.text_area :summary, rows: 4 %> +
-
- <%= translations_form.text_area :summary, rows: 4 %> -
- -
- <%= translations_form.text_area :description, rows: 8 %> -
- <% end %> - -
- <%= render "images/admin_image", imageable: @poll, f: f %> +
+ <%= translations_form.text_area :description, rows: 8 %> +
+ <% end %>
-
-
- <%= f.check_box :geozone_restricted, data: { checkbox_toggle: "#geozones" } %> +
+
+ <%= render "images/admin_image", imageable: @poll, f: f %> +
+ +
+
+ <%= f.check_box :geozone_restricted, data: { checkbox_toggle: "#geozones" } %> +
@@ -54,10 +59,13 @@
-
-
- <%= f.submit t("admin.polls.#{admin_submit_action(@poll)}.submit_button"), - class: "button success expanded margin-top" %> +
+
+
+ <%= f.submit t("admin.polls.#{admin_submit_action(@poll)}.submit_button"), + class: "button success expanded margin-top" %> +
+ <% end %> diff --git a/app/views/admin/poll/polls/new.html.erb b/app/views/admin/poll/polls/new.html.erb index 6cc6c0d8f..528b7ff69 100644 --- a/app/views/admin/poll/polls/new.html.erb +++ b/app/views/admin/poll/polls/new.html.erb @@ -1,7 +1,9 @@ -
- <%= back_link_to %> +
+
+ <%= back_link_to %> -

<%= t("admin.polls.new.title") %>

+

<%= t("admin.polls.new.title") %>

+
diff --git a/app/views/admin/poll/questions/_form.html.erb b/app/views/admin/poll/questions/_form.html.erb index c7aadadf8..350f25d75 100644 --- a/app/views/admin/poll/questions/_form.html.erb +++ b/app/views/admin/poll/questions/_form.html.erb @@ -1,4 +1,4 @@ -<%= render "admin/shared/globalize_locales", resource: @question %> +<%= render "shared/globalize_locales", resource: @question %> <%= translatable_form_for(@question, url: form_url) do |f| %> @@ -6,25 +6,33 @@ <%= f.hidden_field :proposal_id %> -
- <% if @poll.present? %> - <%= f.hidden_field :poll_id, value: @poll.id %> - <% elsif @question.poll.present? %> - <%= f.hidden_field :poll_id, value: @question.poll.id %> - <% else %> -
- <% select_options = Poll.all.map { |p| [p.name, p.id] } %> - <%= f.select :poll_id, - options_for_select(select_options), - prompt: t("admin.questions.index.select_poll"), - label: t("admin.questions.new.poll_label") %> +
+
+ <% if @poll.present? %> + <%= f.hidden_field :poll_id, value: @poll.id %> + <% elsif @question.poll.present? %> + <%= f.hidden_field :poll_id, value: @question.poll.id %> + <% else %> +
+ <% select_options = Poll.all.map { |p| [p.name, p.id] } %> + <%= f.select :poll_id, + options_for_select(select_options), + prompt: t("admin.questions.index.select_poll"), + label: t("admin.questions.new.poll_label") %> +
+ <% end %> +
+
+ +
+ <%= f.translatable_fields do |translations_form| %> +
+ <%= translations_form.text_field :title %>
<% end %> +
- <%= f.translatable_fields do |translations_form| %> - <%= translations_form.text_field :title %> - <% end %> - +
<% if !@question.persisted? %> <%= fields_for :votation_type do |votation_f| %>
@@ -56,8 +64,10 @@
<% end %> <% end %> +
-
+
+
<%= f.submit(class: "button success expanded", value: t("shared.save")) %>
diff --git a/app/views/admin/poll/questions/answers/_form.html.erb b/app/views/admin/poll/questions/answers/_form.html.erb index 06194cd96..873ce5785 100644 --- a/app/views/admin/poll/questions/answers/_form.html.erb +++ b/app/views/admin/poll/questions/answers/_form.html.erb @@ -1,4 +1,4 @@ -<%= render "admin/shared/globalize_locales", resource: @answer %> +<%= render "shared/globalize_locales", resource: @answer %> <%= translatable_form_for(@answer, url: form_url) do |f| %> @@ -9,16 +9,21 @@ <%= f.hidden_field :question_id, value: @answer.question_id || @question.id %> - <%= f.translatable_fields do |translations_form| %> - <%= translations_form.text_field :title %> +
+ <%= f.translatable_fields do |translations_form| %> +
+ <%= translations_form.text_field :title %> +
+
+ <%= translations_form.cktext_area :description, maxlength: Poll::Question.description_max_length %> +
+ <% end %> +
-
- <%= translations_form.cktext_area :description, maxlength: Poll::Question.description_max_length %> +
+
+ <%= f.submit(class: "button success expanded", value: t("shared.save")) %>
- <% end %> - -
- <%= f.submit(class: "button success expanded", value: t("shared.save")) %>
<% end %> diff --git a/app/views/admin/shared/_common_globalize_locales.html.erb b/app/views/admin/shared/_common_globalize_locales.html.erb deleted file mode 100644 index 085cad58a..000000000 --- a/app/views/admin/shared/_common_globalize_locales.html.erb +++ /dev/null @@ -1,20 +0,0 @@ -
- <% I18n.available_locales.each do |locale| %> -
- <%= link_to t("admin.translations.remove_language"), "#", - id: "js_delete_#{locale}", - style: display_translation_style(resource, locale), - class: "delete js-delete-language", - data: { locale: locale } %> -
- <% end %> - - <%= render "admin/shared/globalize_tabs", resource: resource, display_style: display_style %> - -
- <%= select_tag :translation_locale, - options_for_locale_select, - prompt: t("admin.translations.add_language"), - class: "js-globalize-locale" %> -
-
diff --git a/app/views/admin/shared/_globalize_locales.html.erb b/app/views/admin/shared/_globalize_locales.html.erb deleted file mode 100644 index 1dd35e79e..000000000 --- a/app/views/admin/shared/_globalize_locales.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -<%= render "admin/shared/common_globalize_locales", - resource: resource, - display_style: lambda { |locale| enable_translation_style(resource, locale) } %> diff --git a/app/views/admin/shared/_globalize_tabs.html.erb b/app/views/admin/shared/_globalize_tabs.html.erb deleted file mode 100644 index 9b9fc81af..000000000 --- a/app/views/admin/shared/_globalize_tabs.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -
    - <% I18n.available_locales.each do |locale| %> -
  • - <%= link_to name_for_locale(locale), "#", - style: display_style.call(locale), - class: "js-globalize-locale-link #{highlight_class(resource, locale)}", - data: { locale: locale }, - remote: true %> -
  • - <% end %> -
diff --git a/app/views/admin/site_customization/information_texts/_globalize_locales.html.erb b/app/views/admin/site_customization/information_texts/_globalize_locales.html.erb index ebb900379..ef93a7ae7 100644 --- a/app/views/admin/site_customization/information_texts/_globalize_locales.html.erb +++ b/app/views/admin/site_customization/information_texts/_globalize_locales.html.erb @@ -1,3 +1,4 @@ -<%= render "admin/shared/common_globalize_locales", +<%= render "shared/common_globalize_locales", resource: nil, - display_style: lambda { |locale| site_customization_display_translation_style(locale) } %> + display_style: lambda { |locale| site_customization_display_translation_style(locale) }, + manage_languages: defined?(manage_languages) ? manage_languages : true %> diff --git a/app/views/admin/site_customization/pages/_form.html.erb b/app/views/admin/site_customization/pages/_form.html.erb index 90075a24b..0411a5311 100644 --- a/app/views/admin/site_customization/pages/_form.html.erb +++ b/app/views/admin/site_customization/pages/_form.html.erb @@ -1,4 +1,4 @@ -<%= render "admin/shared/globalize_locales", resource: @page %> +<%= render "shared/globalize_locales", resource: @page %> <%= translatable_form_for [:admin, @page], html: {class: "edit_page", data: {watch_changes: true}} do |f| %> <% if @page.errors.any? %> @@ -13,41 +13,51 @@
<% end %> +
+
+
+
-
-
+
+

<%= t("admin.site_customization.pages.form.options") %>

+ <%= f.label :status %> + <% ::SiteCustomization::Page::VALID_STATUSES.each do |status| %> + <%= f.radio_button :status, status, label: false %> + <%= f.label "status_#{status}", t("admin.site_customization.pages.page.status_#{status}") %> +
+ <% end %> + + <%= f.check_box :more_info_flag, class: "small" %> + <%= f.check_box :print_content_flag %> +
+ +
+ <%= f.label :slug %> +

<%= t("admin.site_customization.pages.new.slug_help_html") %> + <%= f.text_field :slug, label: false, size: 80, maxlength: 80 %> +

-
-

<%= t("admin.site_customization.pages.form.options") %>

- <%= f.label :status %> - <% ::SiteCustomization::Page::VALID_STATUSES.each do |status| %> - <%= f.radio_button :status, status, label: false %> - <%= f.label "status_#{status}", t("admin.site_customization.pages.page.status_#{status}") %> -
- <% end %> - - <%= f.check_box :more_info_flag, class: "small" %> - <%= f.check_box :print_content_flag %> +
+
+
+ <%= f.translatable_fields do |translations_form| %> +
+ <%= translations_form.text_field :title %> +
+
+ <%= translations_form.text_field :subtitle %> +
+
+ <%= translations_form.cktext_area :content, + ckeditor: { language: I18n.locale, toolbar: "admin" } %> +
+ <% end %> +
-
- <%= f.label :slug %> -

<%= t("admin.site_customization.pages.new.slug_help_html") %> - <%= f.text_field :slug, label: false, size: 80, maxlength: 80 %> -

-
-
- <%= f.translatable_fields do |translations_form| %> - <%= translations_form.text_field :title %> - <%= translations_form.text_field :subtitle %> -
- <%= translations_form.cktext_area :content, - ckeditor: { language: I18n.locale, toolbar: "admin" } %> -
- <% end %> - -
+
+
<%= f.submit class: "button success expanded" %>
diff --git a/app/views/admin/site_customization/pages/edit.html.erb b/app/views/admin/site_customization/pages/edit.html.erb index 716652079..1965b636f 100644 --- a/app/views/admin/site_customization/pages/edit.html.erb +++ b/app/views/admin/site_customization/pages/edit.html.erb @@ -3,11 +3,12 @@ <% end %> <%= back_link_to admin_site_customization_pages_path %> +
+
+

<%= t("admin.site_customization.pages.edit.title", page_title: @page.title) %>

-
-

<%= t("admin.site_customization.pages.edit.title", page_title: @page.title) %>

- - <%= link_to t("admin.site_customization.pages.index.delete"), admin_site_customization_page_path(@page), method: :delete, class: "delete float-right" %> + <%= link_to t("admin.site_customization.pages.index.delete"), admin_site_customization_page_path(@page), method: :delete, class: "delete float-right" %> +
<%= render "form" %> diff --git a/app/views/admin/site_customization/pages/new.html.erb b/app/views/admin/site_customization/pages/new.html.erb index b180e73d7..dd6fdddd6 100644 --- a/app/views/admin/site_customization/pages/new.html.erb +++ b/app/views/admin/site_customization/pages/new.html.erb @@ -3,9 +3,10 @@ <% end %> <%= back_link_to admin_site_customization_pages_path %> - -
-

<%= t("admin.site_customization.pages.new.title") %>

+
+
+

<%= t("admin.site_customization.pages.new.title") %>

+
<%= render "form" %> diff --git a/app/views/admin/widget/cards/_form.html.erb b/app/views/admin/widget/cards/_form.html.erb index 413be15d1..ab0762859 100644 --- a/app/views/admin/widget/cards/_form.html.erb +++ b/app/views/admin/widget/cards/_form.html.erb @@ -1,41 +1,55 @@ -<%= render "admin/shared/globalize_locales", resource: @card %> +<%= render "shared/globalize_locales", resource: @card %> <%= translatable_form_for [:admin, @card] do |f| %> - <%= f.translatable_fields do |translations_form| %> -
- <%= translations_form.text_field :label %> -
+
+ <%= f.translatable_fields do |translations_form| %> +
+ <%= translations_form.text_field :label %> +
- <%= translations_form.text_field :title %> +
+ <%= translations_form.text_field :title %> +
- <%= translations_form.text_area :description, rows: 5 %> +
+ <%= translations_form.text_area :description, rows: 5 %> +
-
- <%= translations_form.text_field :link_text %> -
- <% end %> - -
- <%= f.text_field :link_url %> +
+ <%= translations_form.text_field :link_text %> +
+ <% end %>
- <% unless @card.header? %> - <%= f.label :columns %> -

<%= t("admin.site_customization.pages.cards.columns_help") %>

-
- <%= f.select :columns, (1..12), label: false %> +
+
+ <%= f.text_field :link_url %>
- <% end %> +
+ +
+ <% unless @card.header? %> +
+ <%= f.label :columns %> +

<%= t("admin.site_customization.pages.cards.columns_help") %>

+
+ <%= f.select :columns, (1..12), label: false %> +
+
+ <% end %> +
<%= f.hidden_field :header, value: @card.header? %> <%= f.hidden_field :site_customization_page_id, value: @card.site_customization_page_id %> - -
-
- <%= render "images/nested_image", imageable: @card, f: f %> +
+
+
+ <%= render "images/nested_image", imageable: @card, f: f %> +
+
+
+ <%= f.submit(t("admin.homepage.#{action_name}.#{@card.header? ? "submit_header" : "submit_card"}"), class: "button success") %>
- - <%= f.submit(t("admin.homepage.#{action_name}.#{@card.header? ? "submit_header" : "submit_card"}"), class: "button success") %> <% end %> diff --git a/app/views/budgets/investments/_form.html.erb b/app/views/budgets/investments/_form.html.erb index dcc62d92d..39266eb5a 100644 --- a/app/views/budgets/investments/_form.html.erb +++ b/app/views/budgets/investments/_form.html.erb @@ -1,28 +1,36 @@ -<%= form_for(@investment, url: form_url, method: :post, html: { multipart: true }) do |f| %> +<%= translatable_form_for(@investment, url: form_url, method: :post, html: { multipart: true }) do |f| %> + <%= render "shared/errors", resource: @investment %> -
+
<%= f.select :heading_id, budget_heading_select_options(@budget), {include_blank: true, } %>
- -
- <%= f.text_field :title, - maxlength: Budget::Investment.title_max_length, - data: { js_suggest_result: "js_suggest_result", - js_suggest: "#js-suggest", - js_url: suggest_budget_investments_path(@budget) } %> +
+
+ <%= render "shared/globalize_locales", resource: @investment %> +
-
+ + <%= f.translatable_fields do |translations_form| %> +
+ <%= translations_form.text_field :title, + maxlength: Budget::Investment.title_max_length, + data: { js_suggest_result: "js_suggest_result", + js_suggest: ".js-suggest", + js_url: suggest_budget_investments_path(@budget) } %> +
+
+ +
+ <%= translations_form.cktext_area :description, + maxlength: Budget::Investment.description_max_length, + ckeditor: { language: I18n.locale } %> +
+ <% end %> <%= f.invisible_captcha :subtitle %> -
- <%= f.cktext_area :description, - maxlength: Budget::Investment.description_max_length, - ckeditor: { language: I18n.locale } %> -
- <% if feature?(:allow_images) %>
<%= render "images/nested_image", imageable: @investment, f: f %> diff --git a/app/views/debates/_form.html.erb b/app/views/debates/_form.html.erb index 27884b47e..33f60dd91 100644 --- a/app/views/debates/_form.html.erb +++ b/app/views/debates/_form.html.erb @@ -1,17 +1,27 @@ -<%= form_for(@debate) do |f| %> +<%= render "shared/globalize_locales", resource: @debate %> + +<%= translatable_form_for(@debate) do |f| %> <%= render "shared/errors", resource: @debate %> -
-
- <%= f.label :title, t("debates.form.debate_title") %> - <%= f.text_field :title, maxlength: Debate.title_max_length, placeholder: t("debates.form.debate_title"), label: false, data: {js_suggest_result: "js_suggest_result", js_suggest: "#js-suggest", js_url: suggest_debates_path}%> -
-
-
- <%= f.label :description, t("debates.form.debate_text") %> - <%= f.cktext_area :description, maxlength: Debate.description_max_length, ckeditor: { language: I18n.locale }, label: false %> -
+
+ <%= f.translatable_fields do |translations_form| %> +
+ <%= translations_form.text_field :title, + maxlength: Debate.title_max_length, + placeholder: t("debates.form.debate_title"), + data: { js_suggest_result: "js_suggest_result", + js_suggest: ".js-suggest", + js_url: suggest_debates_path } %> +
+
+ +
+ <%= translations_form.cktext_area :description, + maxlength: Debate.description_max_length, + ckeditor: { language: I18n.locale } %> +
+ <% end %> <%= f.invisible_captcha :subtitle %> diff --git a/app/views/layouts/_header.html.erb b/app/views/layouts/_header.html.erb index 03014f740..e93075833 100644 --- a/app/views/layouts/_header.html.erb +++ b/app/views/layouts/_header.html.erb @@ -1,4 +1,7 @@
+ <% if display_remote_translation_info?(@remote_translations, I18n.locale) %> + <%= render "shared/remote_translations_button", remote_translations: @remote_translations %> + <% end %>