diff --git a/Gemfile b/Gemfile index ee41bfb3b..15c640607 100644 --- a/Gemfile +++ b/Gemfile @@ -48,7 +48,7 @@ gem 'newrelic_rpm' gem 'whenever', '~> 0.9.0', require: false gem 'jbuilder', '~> 2.1' -gem 'rails3-jquery-autocomplete', '~> 1.0' +gem 'rails3-jquery-autocomplete' gem 'will_paginate', '~> 3.0' gem 'meta-tags', '~> 2.0', require: 'meta_tags' gem "haml-rails", '~> 0.5' @@ -56,6 +56,7 @@ gem 'jquery-rails', '~> 2.3' gem 'jquery-migrate-rails' gem 'ruby-haml-js', '~> 0.0.5' gem 'slim' +gem 'simple_form' gem 'friendly_id', '~> 5.0' gem 'rack-throttle', '~> 0.3.0' diff --git a/Gemfile.lock b/Gemfile.lock index 3201da1dd..b7c7a2616 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -450,6 +450,9 @@ GEM shoulda-context (1.2.1) shoulda-matchers (2.6.2) activesupport (>= 3.0.0) + simple_form (3.0.2) + actionpack (~> 4.0) + activemodel (~> 4.0) sinatra (1.4.5) rack (~> 1.4) rack-protection (~> 1.4) @@ -500,7 +503,7 @@ GEM treetop (1.4.15) polyglot polyglot (>= 0.3.1) - tzinfo (0.3.41) + tzinfo (0.3.42) uglifier (2.5.3) execjs (>= 0.3.0) json (>= 1.8.0) @@ -592,7 +595,7 @@ DEPENDENCIES rack-throttle (~> 0.3.0) rails (= 4.0.9) rails3-generators - rails3-jquery-autocomplete (~> 1.0) + rails3-jquery-autocomplete rake rdiscount redcarpet (~> 3.1) @@ -612,6 +615,7 @@ DEPENDENCIES shotgun shoulda shoulda-matchers + simple_form sitemap_generator skype slim diff --git a/app/assets/javascripts/angular-new/platforms/automatic_metadata_regeneration_controller.js.coffee b/app/assets/javascripts/angular-new/platforms/automatic_metadata_regeneration_controller.js.coffee new file mode 100644 index 000000000..a828cc7a6 --- /dev/null +++ b/app/assets/javascripts/angular-new/platforms/automatic_metadata_regeneration_controller.js.coffee @@ -0,0 +1,18 @@ +RosaABF.controller 'AutomaticMetadataRegenerationController', ['$scope', '$http', ($scope, $http) -> + + # See: Platfrom::AUTOMATIC_METADATA_REGENERATIONS + $scope.items = + day: 'platform.automatic_metadata_regeneration.day' + week: 'platform.automatic_metadata_regeneration.week' + + $scope.platform_id = null + + $scope.update = -> + path = Routes.platform_path($scope.platform_id) + params = + platform: + automatic_metadata_regeneration: $scope.amr + format: 'json' + $http.put(path,params) + +] \ No newline at end of file diff --git a/app/assets/javascripts/new_application.js b/app/assets/javascripts/new_application.js index b1cf6c68c..5946229f4 100644 --- a/app/assets/javascripts/new_application.js +++ b/app/assets/javascripts/new_application.js @@ -3,7 +3,7 @@ //= require jquery-ui //= require js-routes -// require autocomplete-rails +//= require autocomplete-rails // require extra/autocomplete-form //= require bootstrap-sprockets diff --git a/app/controllers/platforms/platforms_controller.rb b/app/controllers/platforms/platforms_controller.rb index 11034d0c9..b1a9269e0 100644 --- a/app/controllers/platforms/platforms_controller.rb +++ b/app/controllers/platforms/platforms_controller.rb @@ -19,8 +19,9 @@ class Platforms::PlatformsController < Platforms::BaseController end def new - @admin_uname = current_user.uname - @admin_id = current_user.id + @admin_uname = current_user.uname + @admin_id = current_user.id + @platform = Platform.new end def edit diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 3932e0f83..eb0192ff4 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -56,7 +56,7 @@ module ApplicationHelper end def alert_class(type) - case type + case type.to_s when 'error' 'alert-danger' when 'notice' diff --git a/app/helpers/platforms_helper.rb b/app/helpers/platforms_helper.rb index 68ac50fce..ce13b0067 100644 --- a/app/helpers/platforms_helper.rb +++ b/app/helpers/platforms_helper.rb @@ -1,5 +1,11 @@ module PlatformsHelper + def platform_visibility_options + Platform::VISIBILITIES.map do |v| + [ I18n.t("activerecord.attributes.platform.visibility_types.#{v}"), v ] + end + end + def repository_name_postfix(platform) return "" unless platform return platform.released ? '/update' : '/release' diff --git a/app/models/platform.rb b/app/models/platform.rb index 080728199..37dfe8388 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -107,7 +107,10 @@ class Platform < ActiveRecord::Base :description, :released, :platform_arch_settings_attributes, - :automatic_metadata_regeneration + :automatic_metadata_regeneration, + :admin_id + + attr_accessor :admin_id attr_readonly :name, :distrib_type, :parent_platform_id, :platform_type diff --git a/app/views/platforms/platforms/_form.html.haml b/app/views/platforms/platforms/_form.html.haml deleted file mode 100644 index 0251c5e22..000000000 --- a/app/views/platforms/platforms/_form.html.haml +++ /dev/null @@ -1,56 +0,0 @@ -- unless ['edit', 'update'].include? controller.action_name - .leftlist= f.label :name, class: :label - .rightlist= f.text_field :name, class: 'text_field' - .both - -.leftlist= f.label :description, class: :label -.rightlist= f.text_area :description, class: 'text_field' -.both - -- unless ['edit', 'update'].include? controller.action_name - .leftlist= f.label :distrib_type, class: :label - .rightlist= f.select :distrib_type, options_for_select(APP_CONFIG['distr_types']) - .both - - .leftlist= f.label :visibility, class: :label - .rightlist= f.select :visibility, options_for_select(Platform::VISIBILITIES.map{ |v| [t("activerecord.attributes.platform.visibility_types.#{v}"), v] }) - .both - - -#.leftlist= f.label :parent, class: :label - .rightlist= f.collection_select :parent_platform_id, Platform.all, :id, :description, include_blank: true - .both - -- unless @platform.platform_type.in? ['personal'] - .leftlist= f.label :released, class: :label - .rightlist= f.check_box :released, class: 'check_box' - .both - - .leftlist= label_tag "", t("layout.platforms.admin_id"), class: :label - .rightlist= autocomplete_field_tag 'admin_id', @admin_uname, autocomplete_user_uname_autocompletes_path, id_element: '#admin_id_field' - = hidden_field_tag 'admin_id', @admin_id, id: 'admin_id_field' - .both - - - if ['edit', 'update'].include? controller.action_name - %h3= t('layout.platform_arch_settings.extra_settings') - - %table.tablesorter{cellpadding: "0", cellspacing: "0"} - %thead - %tr - %th.lpadding16= t("activerecord.models.arch") - %th.lpadding16= t("activerecord.attributes.platform_arch_setting.default") - %th.lpadding16= t("activerecord.attributes.platform_arch_setting.time_living") - %tbody - - platform_arch_settings(@platform).each do |setting| - %tr{class: cycle("odd", "even")} - = f.fields_for :platform_arch_settings, setting do |s_form| - %td - = setting.arch.name - = s_form.hidden_field :arch_id - %td.center= s_form.check_box :default, class: 'check_box' - %td.right= s_form.text_field :time_living, value: setting.time_living / 60, class: 'text_field', size: 10 - .both - -.button_block - = f.submit t('layout.save'), data: {'disable-with' => t('layout.saving')} - %span.text_button_padding= t("layout.or") - = link_to t("layout.cancel"), @platform.new_record? ? root_path : platform_path(@platform), class: "button" diff --git a/app/views/platforms/platforms/_form.html.slim b/app/views/platforms/platforms/_form.html.slim new file mode 100644 index 000000000..9ee7ec4fc --- /dev/null +++ b/app/views/platforms/platforms/_form.html.slim @@ -0,0 +1,72 @@ +fieldset + + - unless %w(edit update).include? controller.action_name + = f.input :name + + = f.input :description, as: :text + + - unless %w(edit update).include? controller.action_name + = f.input :distrib_type, + collection: APP_CONFIG['distr_types'], + include_blank: false + + = f.input :visibility, + collection: platform_visibility_options, + include_blank: false + + - unless @platform.personal? + = f.input :released, as: :boolean + = f.input :admin_id, + url: autocomplete_user_uname_autocompletes_path, + as: :autocomplete, + id_element: '#admin_id_field', + input_html: { value: @admin_uname } + = hidden_field_tag 'admin_id', @admin_id, id: 'admin_id_field' + + - if %w(edit update).include? controller.action_name + + - if can? :change_visibility, @platform + dl.dl-horizontal + dt + = t('activerecord.attributes.platform.visibility') + dd + = link_to t("layout.platforms.change_visibility_from_#{@platform.visibility}"), + change_visibility_platform_path(@platform), + method: :post, + data: { confirm: t("layout.platforms.confirm_change_visibility") }, + class: 'btn btn-xs btn-warning' + + h3 + = t('layout.platform_arch_settings.extra_settings') + + + table.table + thead + tr + th.lpadding16= t("activerecord.models.arch") + th.lpadding16= t("activerecord.attributes.platform_arch_setting.default") + th.lpadding16= t("activerecord.attributes.platform_arch_setting.time_living") + tbody + - platform_arch_settings(@platform).each do |setting| + tr + = f.fields_for :platform_arch_settings, setting do |s_form| + td + = setting.arch.name + = s_form.hidden_field :arch_id + td.center + = s_form.input :default, as: :boolean, label: false + td.right + = s_form.input :time_living, + input_html: { value: setting.time_living / 60 }, + label: false + + +.button_block + button type="submit" class="btn btn-default" data-disable-with=t('layout.saving') + = t('layout.save') + |   + = t('layout.or') + |   + = link_to t('layout.cancel'), + @platform.new_record? ? root_path : platform_path(@platform) + diff --git a/app/views/platforms/platforms/edit.html.haml b/app/views/platforms/platforms/edit.html.haml deleted file mode 100644 index 4acd59c65..000000000 --- a/app/views/platforms/platforms/edit.html.haml +++ /dev/null @@ -1,55 +0,0 @@ --set_meta_tags title: [title_object(@platform), t('layout.platforms.edit')] -= render 'submenu' -= render 'sidebar' - -= form_for @platform, url: platform_path(@platform), html: { class: :form } do |f| - = render "form", f: f - -- if can? :change_visibility, @platform - .hr - .leftside= t('activerecord.attributes.platform.visibility') - .rightside= link_to t("layout.platforms.change_visibility_from_#{@platform.visibility}"), - change_visibility_platform_path(@platform), - method: :post, - data: { confirm: t("layout.platforms.confirm_change_visibility") }, - class: 'button' - .both - -- if can? :regenerate_metadata, @platform - .hr - %h3= t('layout.platforms.metadata') - .leftlist= t('activerecord.attributes.regeneration_status.status') - .rightlist= t("layout.regeneration_statuses.statuses.#{@platform.human_status}") - .both - - .leftlist= t('activerecord.attributes.regeneration_status.last_regenerated_at') - .rightlist= @platform.last_regenerated_at - .both - - .leftlist= t('activerecord.attributes.regeneration_status.last_regenerated_status') - .rightlist= t("layout.regeneration_statuses.last_regenerated_statuses.#{@platform.human_regeneration_status}") - .both - - .leftlist= t('activerecord.attributes.regeneration_status.last_regenerated_log_sha1') - .rightlist= link_to_file_store('regeneration.log', @platform.last_regenerated_log_sha1) - .both - - .leftlist= t('activerecord.attributes.platform.automatic_metadata_regeneration') - .rightlist{ 'ng-controller' => 'AutomaticMetadataRegenerationController', 'ng-init' => "platform_id = #{@platform.id}" } - %select{ 'ng-options' => 'k as (v | i18n) for (k, v) in items', 'ng-model' => 'amr', 'ng-change' => 'update()', 'ng-init' => "amr = '#{@platform.automatic_metadata_regeneration.to_s}'" } - %option{ value: '' } - .both - - .leftside - .rightside= link_to t('layout.regeneration_statuses.regenerate_metadata'), regenerate_metadata_platform_path(@platform), method: :put, data: { confirm: t('layout.confirm') }, class: 'button' - .both - -- if can? :destroy, @platform - .hr - .leftside= t("layout.platforms.delete_warning") - .rightside= link_to t("layout.delete"), platform_path(@platform), method: :delete, data: { confirm: t("layout.platforms.confirm_delete") }, class: 'button' -- if can? :clear, @platform - .hr - .leftside= t("layout.repositories.clear_warning") - .rightside= link_to t("layout.repositories.clear"), clear_platform_path(@platform), class: 'button', data: { confirm: t('layout.repositories.clear_confirm') }, method: :put - .both diff --git a/app/views/platforms/platforms/edit.html.slim b/app/views/platforms/platforms/edit.html.slim new file mode 100644 index 000000000..afd3c0810 --- /dev/null +++ b/app/views/platforms/platforms/edit.html.slim @@ -0,0 +1,63 @@ +- set_meta_tags title: [title_object(@platform), t('layout.platforms.edit')] += render 'submenu' + +.container + .row + = simple_form_for @platform do |f| + = render 'form', f: f + + .row.well + + - if can? :regenerate_metadata, @platform + h4= t('layout.platforms.metadata') + + table.table + tbody + tr + td= t('activerecord.attributes.regeneration_status.status') + td= t("layout.regeneration_statuses.statuses.#{@platform.human_status}") + + tr + td= t('activerecord.attributes.regeneration_status.last_regenerated_at') + td= @platform.last_regenerated_at + + tr + td= t('activerecord.attributes.regeneration_status.last_regenerated_status') + td= t("layout.regeneration_statuses.last_regenerated_statuses.#{@platform.human_regeneration_status}") + tr + td= t('activerecord.attributes.regeneration_status.last_regenerated_log_sha1') + td= link_to_file_store('regeneration.log', @platform.last_regenerated_log_sha1) + tr + td= t('activerecord.attributes.platform.automatic_metadata_regeneration') + td ng-controller='AutomaticMetadataRegenerationController' ng-init="platform_id = #{@platform.id}" + select ng-options='k as (v | i18n) for (k, v) in items' ng-model='amr' ng-change='update()' ng-init="amr = '#{@platform.automatic_metadata_regeneration.to_s}'" + option value='' + tr + td + td + br + = link_to t('layout.regeneration_statuses.regenerate_metadata'), + regenerate_metadata_platform_path(@platform), + method: :put, + data: { confirm: t('layout.confirm') }, + class: 'btn btn-xs btn-warning' + + + - if can? :destroy, @platform + hr + p + = t("layout.platforms.delete_warning") + = link_to t("layout.delete"), + platform_path(@platform), + method: :delete, + data: { confirm: t("layout.platforms.confirm_delete") }, + class: 'btn btn-danger' + + - if can? :clear, @platform + p + = t("layout.repositories.clear_warning") + = link_to t("layout.repositories.clear"), + clear_platform_path(@platform), + class: 'btn btn-danger', + data: { confirm: t('layout.repositories.clear_confirm') }, + method: :put diff --git a/app/views/platforms/platforms/new.html.haml b/app/views/platforms/platforms/new.html.haml deleted file mode 100644 index 7be26baf1..000000000 --- a/app/views/platforms/platforms/new.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -%h3= title t("layout.platforms.new_header") - -= form_for :platform, url: platforms_path, html: { class: :form } do |f| - = render "form", f: f diff --git a/app/views/platforms/platforms/new.html.slim b/app/views/platforms/platforms/new.html.slim new file mode 100644 index 000000000..7e9b17b07 --- /dev/null +++ b/app/views/platforms/platforms/new.html.slim @@ -0,0 +1,8 @@ + +.container + .row + h3 + = title t("layout.platforms.new_header") + + = simple_form_for @platform do |f| + = render 'form', f: f diff --git a/config/initializers/simple_form.rb b/config/initializers/simple_form.rb new file mode 100644 index 000000000..1a92369ed --- /dev/null +++ b/config/initializers/simple_form.rb @@ -0,0 +1,149 @@ +# Use this setup block to configure all options available in SimpleForm. +SimpleForm.setup do |config| + # Wrappers are used by the form builder to generate a + # complete input. You can remove any component from the + # wrapper, change the order or even add your own to the + # stack. The options given below are used to wrap the + # whole input. + config.wrappers :default, class: :input, + hint_class: :field_with_hint, error_class: :field_with_errors do |b| + ## Extensions enabled by default + # Any of these extensions can be disabled for a + # given input by passing: `f.input EXTENSION_NAME => false`. + # You can make any of these extensions optional by + # renaming `b.use` to `b.optional`. + + # Determines whether to use HTML5 (:email, :url, ...) + # and required attributes + b.use :html5 + + # Calculates placeholders automatically from I18n + # You can also pass a string as f.input placeholder: "Placeholder" + b.use :placeholder + + ## Optional extensions + # They are disabled unless you pass `f.input EXTENSION_NAME => :lookup` + # to the input. If so, they will retrieve the values from the model + # if any exists. If you want to enable the lookup for any of those + # extensions by default, you can change `b.optional` to `b.use`. + + # Calculates maxlength from length validations for string inputs + b.optional :maxlength + + # Calculates pattern from format validations for string inputs + b.optional :pattern + + # Calculates min and max from length validations for numeric inputs + b.optional :min_max + + # Calculates readonly automatically from readonly attributes + b.optional :readonly + + ## Inputs + b.use :label_input + b.use :hint, wrap_with: { tag: :span, class: :hint } + b.use :error, wrap_with: { tag: :span, class: :error } + end + + # The default wrapper to be used by the FormBuilder. + # config.default_wrapper = :default + config.default_wrapper = :bootstrap + + # Define the way to render check boxes / radio buttons with labels. + # Defaults to :nested for bootstrap config. + # inline: input + label + # nested: label > input + # config.boolean_style = :nested + config.boolean_style = :inline + + # Default class for buttons + config.button_class = 'btn' + + # Method used to tidy up errors. Specify any Rails Array method. + # :first lists the first message for each field. + # Use :to_sentence to list all errors for each field. + # config.error_method = :first + + # Default tag used for error notification helper. + config.error_notification_tag = :div + + # CSS class to add for error notification helper. + config.error_notification_class = 'alert alert-error' + + # ID to add for error notification helper. + # config.error_notification_id = nil + + # Series of attempts to detect a default label method for collection. + # config.collection_label_methods = [ :to_label, :name, :title, :to_s ] + + # Series of attempts to detect a default value method for collection. + # config.collection_value_methods = [ :id, :to_s ] + + # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none. + # config.collection_wrapper_tag = nil + + # You can define the class to use on all collection wrappers. Defaulting to none. + # config.collection_wrapper_class = nil + + # You can wrap each item in a collection of radio/check boxes with a tag, + # defaulting to :span. Please note that when using :boolean_style = :nested, + # SimpleForm will force this option to be a label. + # config.item_wrapper_tag = :span + + # You can define a class to use in all item wrappers. Defaulting to none. + # config.item_wrapper_class = nil + + # How the label text should be generated altogether with the required text. + # config.label_text = lambda { |label, required| "#{required} #{label}" } + + # You can define the class to use on all labels. Default is nil. + config.label_class = 'col-sm-2 control-label' + + # You can define the class to use on all forms. Default is simple_form. + # config.form_class = :simple_form + config.form_class = 'well form-horizontal' + + # You can define which elements should obtain additional classes + # config.generate_additional_classes_for = [:wrapper, :label, :input] + + # Whether attributes are required by default (or not). Default is true. + # config.required_by_default = true + + # Tell browsers whether to use the native HTML5 validations (novalidate form option). + # These validations are enabled in SimpleForm's internal config but disabled by default + # in this configuration, which is recommended due to some quirks from different browsers. + # To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations, + # change this configuration to true. + config.browser_validations = false + + # Collection of methods to detect if a file type was given. + # config.file_methods = [ :mounted_as, :file?, :public_filename ] + + # Custom mappings for input types. This should be a hash containing a regexp + # to match as key, and the input type that will be used when the field name + # matches the regexp as value. + # config.input_mappings = { /count/ => :integer } + + # Custom wrappers for input types. This should be a hash containing an input + # type as key and the wrapper that will be used for all inputs with specified type. + # config.wrapper_mappings = { string: :prepend } + + # Default priority for time_zone inputs. + # config.time_zone_priority = nil + + # Default priority for country inputs. + # config.country_priority = nil + + # When false, do not use translations for labels. + # config.translate_labels = true + + # Automatically discover new inputs in Rails' autoload path. + # config.inputs_discovery = true + + # Cache SimpleForm inputs discovery + # config.cache_discovery = !Rails.env.development? + + # Default class for inputs + # config.input_class = nil + config.input_class = 'form-control' +end diff --git a/config/initializers/simple_form_bootstrap.rb b/config/initializers/simple_form_bootstrap.rb new file mode 100644 index 000000000..b88cee0ef --- /dev/null +++ b/config/initializers/simple_form_bootstrap.rb @@ -0,0 +1,45 @@ +# Use this setup block to configure all options available in SimpleForm. +SimpleForm.setup do |config| + config.wrappers :bootstrap, tag: 'div', class: 'form-group', error_class: 'error' do |b| + b.use :html5 + b.use :placeholder + b.use :label + b.wrapper tag: 'div', class: 'col-sm-10' do |ba| + ba.use :input + ba.use :error, wrap_with: { tag: 'span', class: 'help-inline' } + ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + end + end + + config.wrappers :prepend, tag: 'div', class: "form-group", error_class: 'error' do |b| + b.use :html5 + b.use :placeholder + b.use :label + b.wrapper tag: 'div', class: 'col-sm-10' do |input| + input.wrapper tag: 'div', class: 'input-prepend' do |prepend| + prepend.use :input + end + input.use :hint, wrap_with: { tag: 'span', class: 'help-block' } + input.use :error, wrap_with: { tag: 'span', class: 'help-inline' } + end + end + + config.wrappers :append, tag: 'div', class: "form-group", error_class: 'error' do |b| + b.use :html5 + b.use :placeholder + b.use :label + b.wrapper tag: 'div', class: 'col-sm-10' do |input| + input.wrapper tag: 'div', class: 'input-append' do |append| + append.use :input + end + input.use :hint, wrap_with: { tag: 'span', class: 'help-block' } + input.use :error, wrap_with: { tag: 'span', class: 'help-inline' } + end + end + + # Wrappers for forms and inputs using the Twitter Bootstrap toolkit. + # Check the Bootstrap docs (http://twitter.github.com/bootstrap) + # to learn about the different styles for forms and inputs, + # buttons and other elements. + config.default_wrapper = :bootstrap +end diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml new file mode 100644 index 000000000..0df11fe0f --- /dev/null +++ b/config/locales/simple_form.en.yml @@ -0,0 +1,26 @@ +en: + simple_form: + "yes": 'Yes' + "no": 'No' + required: + text: 'required' + mark: '*' + # You can uncomment the line below if you need to overwrite the whole required html. + # When using html, text and mark won't be used. + # html: '*' + error_notification: + default_message: "Please review the problems below:" + # Labels and hints examples + # labels: + # defaults: + # password: 'Password' + # user: + # new: + # email: 'E-mail to sign in.' + # edit: + # email: 'E-mail.' + # hints: + # defaults: + # username: 'User name to sign in.' + # password: 'No special characters, please.' + diff --git a/config/locales/simple_form.ru.yml b/config/locales/simple_form.ru.yml new file mode 100644 index 000000000..0dd4542d8 --- /dev/null +++ b/config/locales/simple_form.ru.yml @@ -0,0 +1,12 @@ +ru: + simple_form: + "yes": 'Да' + "no": 'Нет' + required: + text: 'обязательное' + mark: '*' + # You can uncomment the line below if you need to overwrite the whole required html. + # When using html, text and mark won't be used. + # html: '*' + error_notification: + default_message: "Обнаружены следующие ошибки:" \ No newline at end of file