diff --git a/Gemfile.lock b/Gemfile.lock index 9783d484..8e3a6be3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -60,17 +60,18 @@ GEM acts_as_tree (1.4.0) activerecord (>= 3.0.0) afm (0.2.0) - arel (3.0.2) + arel (3.0.3) better_errors (1.0.1) coderay (>= 1.0.0) erubis (>= 2.6.6) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) - bootstrap-datepicker-rails (1.1.1.8) + bootstrap-datepicker-rails (1.1.1.9) railties (>= 3.0) builder (3.0.4) - bullet (4.6.0) - uniform_notifier + bullet (4.7.1) + activesupport + uniform_notifier (>= 1.4.0) capistrano (2.13.5) highline net-scp (>= 1.0.0) @@ -104,7 +105,8 @@ GEM daemons (1.1.9) database_cleaner (1.2.0) debug_inspector (0.0.2) - diff-lcs (1.2.4) + diff-lcs (1.2.5) + docile (1.1.0) erubis (2.7.0) eventmachine (1.0.3) exception_notification (4.0.1) @@ -112,15 +114,15 @@ GEM activesupport (>= 3.0.4) execjs (2.0.2) expression_parser (0.9.0) - factory_girl (4.2.0) + factory_girl (4.3.0) activesupport (>= 3.0.0) - factory_girl_rails (4.2.1) - factory_girl (~> 4.2.0) + factory_girl_rails (4.3.0) + factory_girl (~> 4.3.0) railties (>= 3.0.0) faker (1.2.0) i18n (~> 0.5) - ffi (1.9.0) - haml (4.0.3) + ffi (1.9.3) + haml (4.0.4) tilt haml-rails (0.4) actionpack (>= 3.1, < 4.1) @@ -155,6 +157,7 @@ GEM actionpack (>= 3.1) less (~> 2.4.0) libv8 (3.16.14.3) + lockfile (2.1.0) mail (2.5.4) mime-types (~> 1.16) treetop (~> 1.4.8) @@ -176,7 +179,7 @@ GEM mini_portile (0.5.2) mono_logger (1.1.0) multi_json (1.8.2) - mysql2 (0.3.13) + mysql2 (0.3.14) net-scp (1.1.2) net-ssh (>= 2.6.5) net-sftp (2.1.2) @@ -234,9 +237,9 @@ GEM rake (10.1.0) rdoc (3.12.2) json (~> 1.4) - redis (3.0.5) - redis-namespace (1.3.1) - redis (~> 3.0.0) + redis (3.0.6) + redis-namespace (1.3.2) + redis (~> 3.0.4) ref (1.0.5) responders (1.0.0) railties (>= 3.2, < 5) @@ -246,8 +249,8 @@ GEM redis-namespace (~> 1.2) sinatra (>= 0.9.2) vegas (~> 0.1.2) - rspec-core (2.14.6) - rspec-expectations (2.14.3) + rspec-core (2.14.7) + rspec-expectations (2.14.4) diff-lcs (>= 1.1.3, < 2.0) rspec-mocks (2.14.4) rspec-rails (2.14.0) @@ -265,7 +268,7 @@ GEM railties (~> 3.2.0) sass (>= 3.1.10) tilt (~> 1.3) - select2-rails (3.5.0) + select2-rails (3.5.1) thor (~> 0.14) selenium-webdriver (2.37.0) childprocess (>= 0.2.5) @@ -280,10 +283,12 @@ GEM simple_form (2.1.0) actionpack (~> 3.0) activemodel (~> 3.0) - simplecov (0.7.1) - multi_json (~> 1.0) - simplecov-html (~> 0.7.1) - simplecov-html (0.7.1) + simplecov (0.8.1) + docile (~> 1.1.0) + lockfile (>= 2.1.0) + multi_json + simplecov-html (~> 0.8.0) + simplecov-html (0.8.0) sinatra (1.4.4) rack (~> 1.4) rack-protection (~> 1.4) @@ -316,10 +321,10 @@ GEM rails (>= 3.1) railties (>= 3.1) tzinfo (0.3.38) - uglifier (2.3.0) + uglifier (2.3.1) execjs (>= 0.3.0) json (>= 1.8.0) - uniform_notifier (1.3.0) + uniform_notifier (1.4.0) vegas (0.1.11) rack (>= 1.0.0) websocket (1.0.7) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index e83ecc11..c86b173e 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -2,13 +2,10 @@ class Admin::UsersController < Admin::BaseController inherit_resources def index - @users = User.order('nick ASC') + @users = User.natural_order # if somebody uses the search field: - unless params[:user_name].blank? - @users = @users.where("first_name LIKE :user_name OR last_name LIKE :user_name OR nick LIKE :user_name", - user_name: "%#{params[:user_name]}%") - end + @users = @users.natural_search(params[:user_name]) unless params[:user_name].blank? @users = @users.page(params[:page]).per(@per_page) end diff --git a/app/controllers/foodcoop/users_controller.rb b/app/controllers/foodcoop/users_controller.rb index f73147bc..31539dce 100644 --- a/app/controllers/foodcoop/users_controller.rb +++ b/app/controllers/foodcoop/users_controller.rb @@ -1,19 +1,16 @@ class Foodcoop::UsersController < ApplicationController def index - @users = User.order('nick ASC') + @users = User.natural_order # if somebody uses the search field: - unless params[:user_name].blank? - @users = @users.where("first_name LIKE :user_name OR last_name LIKE :user_name OR nick LIKE :user_name", - user_name: "%#{params[:user_name]}%") - end + @users = @users.natural_search(params[:user_name]) unless params[:user_name].blank? if params[:ordergroup_name] @users = @users.joins(:groups).where("groups.type = 'Ordergroup' AND groups.name LIKE ?", "%#{params[:ordergroup_name]}%") end - @users = @users.page(params[:page]).per(@per_page).order('users.nick ASC') + @users = @users.page(params[:page]).per(@per_page) respond_to do |format| format.html # index.html.haml diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 916b33f7..51ca228f 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -2,9 +2,9 @@ class UsersController < ApplicationController # Currently used to display users nick and ids for autocomplete def index - @users = User.where("nick LIKE ?", "%#{params[:q]}%") + @users = User.natural_search(params[:q]) respond_to do |format| - format.json { render :json => @users.map { |u| u.token_attributes } } + format.json { render :json => @users.map(&:token_attributes) } end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 2588ea18..59994432 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -155,13 +155,6 @@ module ApplicationHelper :target => "_blank" end - # offers a link for writing message to user - # checks for nil (useful for relations) - def link_to_user_message_if_valid(user) - user.nil? ? '??' : link_to(user.nick, new_message_path('message[mail_to]' => user.id), - :title => I18n.t('helpers.application.write_message')) - end - def bootstrap_flash flash_messages = [] flash.each do |type, message| @@ -183,4 +176,32 @@ module ApplicationHelper render :partial => 'shared/base_errors', :locals => {:error_messages => messages} end + # show a user, depending on settings + def show_user(user=@current_user, options = {}) + if user.nil? + "?" + elsif FoodsoftConfig[:use_nick] + if options[:full] and options[:markup] + raw "#{h user.nick} (#{h user.first_name} #{h user.last_name})" + elsif options[:full] + "#{user.nick} (#{user.first_name} #{user.last_name})" + else + # when use_nick was changed from false to true, users may exist without nick + user.nick.nil? ? I18n.t('helpers.application.nick_fallback') : user.nick + end + else + "#{user.first_name} #{user.last_name}" + (options[:unique] ? " (\##{user.id})" : '') + end + end + + # render user presentation linking to default action (write message) + def show_user_link(user=@current_user) + if user.nil? + show_user user + else + link_to show_user(user), new_message_path('message[mail_to]' => user.id), + :title => I18n.t('helpers.application.write_message') + end + end + end diff --git a/app/helpers/tasks_helper.rb b/app/helpers/tasks_helper.rb index c123c9ae..f2a9bea5 100644 --- a/app/helpers/tasks_helper.rb +++ b/app/helpers/tasks_helper.rb @@ -2,7 +2,7 @@ module TasksHelper def task_assignments(task) task.assignments.map do |ass| - content_tag :span, ass.user.nick, :class => (ass.accepted? ? 'accepted' : 'unaccepted') + content_tag :span, show_user(ass.user), :class => (ass.accepted? ? 'accepted' : 'unaccepted') end.join(", ").html_safe end diff --git a/app/mailers/mailer.rb b/app/mailers/mailer.rb index 30eb44a7..003e75ed 100644 --- a/app/mailers/mailer.rb +++ b/app/mailers/mailer.rb @@ -1,6 +1,11 @@ # encoding: utf-8 # ActionMailer class that handles all emails for the FoodSoft. class Mailer < ActionMailer::Base + # XXX Quick fix to allow the use of show_user. Proper take would be one of + # (1) Use draper, decorate user + # (2) Create a helper with this method, include here and in ApplicationHelper + helper :application + include ApplicationHelper layout 'email' # Use views/layouts/email.txt.erb @@ -15,7 +20,7 @@ class Mailer < ActionMailer::Base mail subject: "[#{FoodsoftConfig[:name]}] " + message.subject, to: recipient.email, - from: "#{message.sender.nick} <#{message.sender.email}>" + from: "#{show_user(message.sender)} <#{message.sender.email}>" end # Sends an email with instructions on how to reset the password. @@ -26,7 +31,7 @@ class Mailer < ActionMailer::Base @link = new_password_url(id: @user.id, token: @user.reset_password_token) mail :to => @user.email, - :subject => "[#{FoodsoftConfig[:name]}] " + I18n.t('mailer.reset_password.subject', :username => @user.nick) + :subject => "[#{FoodsoftConfig[:name]}] " + I18n.t('mailer.reset_password.subject', :username => show_user(@user)) end # Sends an invite email. @@ -75,7 +80,7 @@ class Mailer < ActionMailer::Base @feedback = feedback mail :to => FoodsoftConfig[:notification]["error_recipients"], - :from => "#{user.nick} <#{user.email}>", + :from => "#{show_user user} <#{user.email}>", :sender => FoodsoftConfig[:notification]["sender_address"], :errors_to => FoodsoftConfig[:notification]["sender_address"], :subject => "[#{FoodsoftConfig[:name]}] " + I18n.t('mailer.feedback.subject', :email => user.email) diff --git a/app/models/article.rb b/app/models/article.rb index a3b4af33..0c809784 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -106,7 +106,7 @@ class Article < ActiveRecord::Base # to get the correspondent shared article def shared_article - @shared_article ||= self.supplier.shared_supplier.shared_articles.find_by_number(self.order_number) + @shared_article ||= self.supplier.shared_supplier.shared_articles.find_by_number(self.order_number) rescue nil end # convert units in foodcoop-size diff --git a/app/models/group.rb b/app/models/group.rb index 092c0119..9c861abd 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -17,7 +17,7 @@ class Group < ActiveRecord::Base # Returns all NONmembers and a checks for possible multiple Ordergroup-Memberships def non_members - User.all(:order => 'nick').reject { |u| users.include?(u) } + User.natural_order.all.reject { |u| users.include?(u) } end def user_tokens=(ids) diff --git a/app/models/message.rb b/app/models/message.rb index e14ad59e..6504489c 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -49,7 +49,7 @@ class Message < ActiveRecord::Base @reply_to = Message.find(message_id) add_recipients([@reply_to.sender]) self.subject = I18n.t('messages.model.reply_subject', :subject => @reply_to.subject) - self.body = I18n.t('messages.model.reply_header', :user => @reply_to.sender.nick, :when => I18n.l(@reply_to.created_at, :format => :short)) + "\n" + self.body = I18n.t('messages.model.reply_header', :user => @reply_to.sender.display, :when => I18n.l(@reply_to.created_at, :format => :short)) + "\n" @reply_to.body.each_line{ |l| self.body += I18n.t('messages.model.reply_indent', :line => l) } end @@ -64,7 +64,7 @@ class Message < ActiveRecord::Base end def sender_name - system_message? ? I18n.t('layouts.foodsoft') : sender.nick rescue "??" + system_message? ? I18n.t('layouts.foodsoft') : sender.display rescue "?" end def recipients @@ -77,7 +77,7 @@ class Message < ActiveRecord::Base begin Mailer.foodsoft_message(self, user).deliver rescue - Rails.logger.warn "Deliver failed for #{user.nick}: #{user.email}" + Rails.logger.warn "Deliver failed for user \##{user.id}: #{user.email}" end end end diff --git a/app/models/ordergroup.rb b/app/models/ordergroup.rb index 0188abcf..bf82afc4 100644 --- a/app/models/ordergroup.rb +++ b/app/models/ordergroup.rb @@ -23,7 +23,7 @@ class Ordergroup < Group "#{contact_phone} (#{contact_person})" end def non_members - User.all(:order => 'nick').reject { |u| (users.include?(u) || u.ordergroup) } + User.natural_order.all.reject { |u| (users.include?(u) || u.ordergroup) } end def value_of_open_orders(exclude = nil) @@ -102,7 +102,7 @@ class Ordergroup < Group # Make sure, that a user can only be in one ordergroup def uniqueness_of_members users.each do |user| - errors.add :user_tokens, I18n.t('ordergroups.model.error_single_group', :user => user.nick) if user.groups.where(:type => 'Ordergroup').size > 1 + errors.add :user_tokens, I18n.t('ordergroups.model.error_single_group', :user => user.display) if user.groups.where(:type => 'Ordergroup').size > 1 end end diff --git a/app/models/user.rb b/app/models/user.rb index c46d950c..3119e29d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -24,15 +24,19 @@ class User < ActiveRecord::Base # makes the current_user (logged-in-user) available in models cattr_accessor :current_user - validates_presence_of :nick, :email + validates_presence_of :email validates_presence_of :password, :on => :create - validates_length_of :nick, :in => 2..25 - validates_uniqueness_of :nick, :case_sensitive => false validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i validates_uniqueness_of :email, :case_sensitive => false validates_length_of :first_name, :in => 2..50 validates_confirmation_of :password validates_length_of :password, :in => 5..25, :allow_blank => true + # allow nick to be nil depending on foodcoop config + # TODO Rails 4 may have a more beautiful way + # http://stackoverflow.com/questions/19845910/conditional-allow-nil-part-of-validation + validates_length_of :nick, :in => 2..25, :allow_nil => true, :unless => Proc.new { FoodsoftConfig[:use_nick] } + validates_length_of :nick, :in => 2..25, :allow_nil => false, :if => Proc.new { FoodsoftConfig[:use_nick] } + validates_uniqueness_of :nick, :case_sensitive => false, :allow_nil => true # allow_nil in length validation before_validation :set_password after_initialize do @@ -55,6 +59,22 @@ class User < ActiveRecord::Base self.settings.merge!(key, value) end end + + # sorted by display name + def self.natural_order + # would be sensible to match ApplicationController#show_user + if FoodsoftConfig[:use_nick] + order('nick ASC') + else + order('first_name ASC, last_name ASC') + end + end + + # search by (nick)name + def self.natural_search(q) + # we always use both nick and name, to make sure a user is found + where("CONCAT(first_name, CONCAT(' ', last_name)) LIKE :q OR nick LIKE :q", q: "%#{q}%") + end def locale settings.profile['language'] @@ -132,8 +152,8 @@ class User < ActiveRecord::Base self.groups.find(:all, :conditions => {:type => ""}) end - def self.authenticate(nick, password) - user = find_by_nick(nick) + def self.authenticate(login, password) + user = (find_by_nick(login) or find_by_email(login)) if user && user.has_password(password) user else @@ -141,8 +161,21 @@ class User < ActiveRecord::Base end end + # XXX this is view-related; need to move out things like token_attributes + # then this can be removed + def display + # would be sensible to match ApplicationHelper#show_user + if FoodsoftConfig[:use_nick] + nick.nil? ? I18n.t('helpers.application.nick_fallback') : nick + else + name + end + end + def token_attributes - {:id => id, :name => "#{nick} (#{ordergroup.try(:name)})"} + # would be sensible to match ApplicationController#show_user + # this should not be part of the model anyway + {:id => id, :name => "#{display} (#{ordergroup.try(:name)})"} end end diff --git a/app/views/admin/base/index.html.haml b/app/views/admin/base/index.html.haml index fbe63c09..ed13be09 100644 --- a/app/views/admin/base/index.html.haml +++ b/app/views/admin/base/index.html.haml @@ -9,13 +9,15 @@ %table.table.table-striped %thead %tr - %th= t '.username' + - if FoodsoftConfig[:use_nick] + %th= t '.username' %th= t '.name' %th= t '.created_at' - for user in @users %tr{:class => cycle('even','odd', :name => 'users')} - %td= link_to user.nick, [:admin, user] - %td=h user.name + %td= link_to show_user(user), [:admin, user] + - if FoodsoftConfig[:use_nick] + %td= link_to user.name %td= format_date(user.created_on) = link_to t('.all_users'), admin_users_path | diff --git a/app/views/admin/users/_users.html.haml b/app/views/admin/users/_users.html.haml index 3f8b1df6..5fd16bf5 100644 --- a/app/views/admin/users/_users.html.haml +++ b/app/views/admin/users/_users.html.haml @@ -4,7 +4,8 @@ %table.table.table-striped %thead %tr - %th= t '.login' + - if FoodsoftConfig[:use_nick] + %th= t '.login' %th= t '.name' %th= t '.email' %th= t 'admin.access_to' @@ -13,8 +14,9 @@ %tbody - for user in @users %tr - %td= link_to user.nick, [:admin, user] - %td= user.name + %td= link_to show_user(user), [:admin, user] + - if FoodsoftConfig[:use_nick] + %td= user.name %td= user.email %td= format_roles(user) %td= format_time(user.last_login) diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index 4d0cd1ab..2321ccdb 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -1,4 +1,4 @@ -- title @user.nick +- title show_user(@user) .row-fluid .span3 @@ -6,8 +6,9 @@ %h4= t '.person' %p= t '.member_since', time: distance_of_time_in_words(Time.now, @user.created_on) %dl - %dt= t '.nick' - %dd= @user.nick + - if FoodsoftConfig[:use_nick] + %dt= t '.nick' + %dd= @user.nick %dt= t '.name' %dd= h @user.name %dt= t '.email' diff --git a/app/views/finance/balancing/_orders.html.haml b/app/views/finance/balancing/_orders.html.haml index 0fa52428..6973aa32 100644 --- a/app/views/finance/balancing/_orders.html.haml +++ b/app/views/finance/balancing/_orders.html.haml @@ -16,7 +16,7 @@ %td= link_to truncate(order.name), new_finance_order_path(order_id: order.id) %td=h format_time(order.ends) unless order.ends.nil? %td= order.closed? ? t('.cleared', amount: number_to_currency(order.foodcoop_result)) : t('.ended') - %td= order.updated_by.nil? ? '??' : order.updated_by.nick + %td= show_user(order.updated_by) %td - unless order.closed? = link_to t('.clear'), new_finance_order_path(order_id: order.id), class: 'btn btn-mini btn-primary' diff --git a/app/views/finance/financial_transactions/_transactions.html.haml b/app/views/finance/financial_transactions/_transactions.html.haml index ecfd1c9e..64b1c938 100644 --- a/app/views/finance/financial_transactions/_transactions.html.haml +++ b/app/views/finance/financial_transactions/_transactions.html.haml @@ -12,6 +12,6 @@ - @financial_transactions.each do |t| %tr %td= format_time(t.created_on) - %td= h t.user.nil? ? '??' : t.user.nick + %td= h show_user(t.user) %td= h t.note %td.currency{:style => "color:#{t.amount < 0 ? 'red' : 'black'}; width:5em"}= number_to_currency(t.amount) diff --git a/app/views/foodcoop/ordergroups/_ordergroups.html.haml b/app/views/foodcoop/ordergroups/_ordergroups.html.haml index 7c7780ee..20fbd0c9 100644 --- a/app/views/foodcoop/ordergroups/_ordergroups.html.haml +++ b/app/views/foodcoop/ordergroups/_ordergroups.html.haml @@ -13,7 +13,7 @@ - for ordergroup in @ordergroups %tr %td= ordergroup.name - %td=h ordergroup.users.collect { |u| u.nick }.join(", ") + %td=h ordergroup.users.collect { |u| show_user(u) }.join(", ") %td= format_date ordergroup.orders.order('orders.starts DESC').first.try(:starts) %td= link_to_new_message(message_params: {group_id: ordergroup.id}) diff --git a/app/views/foodcoop/users/_users.html.haml b/app/views/foodcoop/users/_users.html.haml index 1ecbb107..df39c742 100644 --- a/app/views/foodcoop/users/_users.html.haml +++ b/app/views/foodcoop/users/_users.html.haml @@ -4,7 +4,8 @@ %table.table.table-striped %thead %tr - %th= heading_helper User, :nick + - if FoodsoftConfig[:use_nick] + %th= heading_helper User, :nick %th= heading_helper User, :name %th= heading_helper User, :email %th= heading_helper User, :phone @@ -13,8 +14,9 @@ %tbody - for user in @users %tr - %td= user.nick - %td= user.name if @current_user.role_admin? || user.settings.profile["name_is_public"] + - if FoodsoftConfig[:use_nick] + %td= show_user user + %td= user.name if @current_user.role_admin? || user.settings.profile["name_is_public"] || !FoodsoftConfig[:use_nick] %td= user.email if @current_user.role_admin? || user.settings.profile["email_is_public"] %td= user.phone if @current_user.role_admin? || user.settings.profile["phone_is_public"] %td= user.ordergroup_name diff --git a/app/views/group_orders/_form.html.haml b/app/views/group_orders/_form.html.haml index 0d299b87..a0b11791 100644 --- a/app/views/group_orders/_form.html.haml +++ b/app/views/group_orders/_form.html.haml @@ -30,7 +30,7 @@ %dt= t '.note' %dd= @order.note %dt= t '.created_by' - %dd= link_to_user_message_if_valid(@order.created_by) + %dd= show_user_link(@order.created_by) %dt= t '.ending' %dd= format_time(@order.ends) - unless @order.stockit? or @order.supplier.min_order_quantity.blank? @@ -40,7 +40,7 @@ %dd= number_to_currency @order.sum %dt= t '.last_update' %dd - = @group_order.updated_by.nick if @group_order.updated_by + = show_user(@group_order.updated_by) if @group_order.updated_by (#{format_time(@group_order.updated_on)}) %dt= t '.funds' %dd= number_to_currency(@ordering_data[:available_funds]) diff --git a/app/views/group_orders/show.html.haml b/app/views/group_orders/show.html.haml index ed3079ca..27a88eff 100644 --- a/app/views/group_orders/show.html.haml +++ b/app/views/group_orders/show.html.haml @@ -22,7 +22,7 @@ - else = t '.not_ordered' - if @order.closed? - %p= t '.closed_by', user: @order.updated_by.nick + %p= t '.closed_by', user: show_user(@order.updated_by) = link_to t('.comment'), "#comments" // Article box diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml index 3e70be75..236d5c5c 100644 --- a/app/views/home/index.html.haml +++ b/app/views/home/index.html.haml @@ -57,7 +57,7 @@ - for ft in current_user.ordergroup.financial_transactions.limit(5).order('created_on DESC') %tr %td= format_time(ft.created_on) - %td= h(ft.user.nil? ? '?' : ft.user.nick) + %td= h(show_user(ft.user)) %td= h(ft.note) - color = ft.amount < 0 ? 'red' : 'black' %td{:style => "color:#{color}; width:5em", :class => "currency"}= number_to_currency(ft.amount) diff --git a/app/views/home/ordergroup.html.haml b/app/views/home/ordergroup.html.haml index 215d2826..213ef0c9 100644 --- a/app/views/home/ordergroup.html.haml +++ b/app/views/home/ordergroup.html.haml @@ -11,7 +11,7 @@ = number_to_currency(@ordergroup.get_available_funds()) %p %b= Ordergroup.human_attribute_name(:user_tokens) + ':' - = @ordergroup.memberships.map{|m| m.user.nick}.join(', ') + = @ordergroup.memberships.map{|m| show_user m.user}.join(', ') = link_to t('.invite'), new_invite_path(:id => @ordergroup), :remote => true, class: 'btn btn-primary' .span8 %h2= t('.account_summary') diff --git a/app/views/home/profile.html.haml b/app/views/home/profile.html.haml index 6a54fce6..0b0364a1 100644 --- a/app/views/home/profile.html.haml +++ b/app/views/home/profile.html.haml @@ -3,7 +3,7 @@ .row-fluid .span7 %h3 - = h(t('.user.title', user: @current_user.nick)) + = h(t('.user.title', user: show_user)) %small= t '.user.since', when: distance_of_time_in_words(Time.now, @current_user.created_on) = simple_form_for(@current_user, :url => update_profile_path) do |f| = render :partial => 'shared/user_form_fields', :locals => {:f => f} diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 2feb4fa3..f926e500 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -4,7 +4,7 @@ %ul.nav.nav-pills.pull-right %li.dropdown %a.dropdown-toggle(data-toggle="dropdown" href="#") - = current_user.nick + = show_user current_user %b.caret %ul.dropdown-menu %li= link_to t('.profile'), my_profile_path diff --git a/app/views/login/accept_invitation.html.haml b/app/views/login/accept_invitation.html.haml index 07489ebc..11865bcb 100644 --- a/app/views/login/accept_invitation.html.haml +++ b/app/views/login/accept_invitation.html.haml @@ -1,6 +1,6 @@ - content_for :javascript do :javascript - $('user_nick').focus(); + $(#{FoodsoftConfig[:use_nick] ? 'user_nick' : 'user_first_name'}).focus(); - title t('.title', name: FoodsoftConfig[:name]) = t('.body', group: h(@invite.group.name), foodcoop: h(FoodsoftConfig[:name])).html_safe diff --git a/app/views/login/new_password.html.haml b/app/views/login/new_password.html.haml index ea928051..2aa21e57 100644 --- a/app/views/login/new_password.html.haml +++ b/app/views/login/new_password.html.haml @@ -1,5 +1,5 @@ - title t('.title') -= t('.body', user: h(@user.nick)).html_safe += raw t('.body', user: h(show_user(@user))) = simple_form_for @user, :url => update_password_path(@user.id, :token => @user.reset_password_token) do |form| = form.input :password = form.input :password_confirmation diff --git a/app/views/mailer/feedback.text.haml b/app/views/mailer/feedback.text.haml index 7708e297..a63e2fdc 100644 --- a/app/views/mailer/feedback.text.haml +++ b/app/views/mailer/feedback.text.haml @@ -1,3 +1,3 @@ -= t '.header', user: @user.nick, date: I18n.l(Time.now, :format => :short) += t '.header', user: show_user(@user), date: I18n.l(Time.now, :format => :short) \ = @feedback diff --git a/app/views/mailer/negative_balance.text.haml b/app/views/mailer/negative_balance.text.haml index 51d4f6e7..94734be5 100644 --- a/app/views/mailer/negative_balance.text.haml +++ b/app/views/mailer/negative_balance.text.haml @@ -1 +1 @@ -= t '.text', group: @group.name, when: @transaction.created_on.strftime('%d.%m.%Y um %H:%M'), balance: @group.account_balance, amount:@transaction.amount, note: @transaction.note, user: @transaction.user.nick, foodcoop: FoodsoftConfig[:name] += t '.text', group: @group.name, when: @transaction.created_on.strftime('%d.%m.%Y um %H:%M'), balance: @group.account_balance, amount:@transaction.amount, note: @transaction.note, user: show_user(@transaction.user), foodcoop: FoodsoftConfig[:name] diff --git a/app/views/mailer/order_result.text.haml b/app/views/mailer/order_result.text.haml index 8d64fbd2..cfe6cf78 100644 --- a/app/views/mailer/order_result.text.haml +++ b/app/views/mailer/order_result.text.haml @@ -1,4 +1,4 @@ -= raw t '.text0', ordergroup: @group_order.ordergroup.name, order: @order.name, when: I18n.l(@order.ends), user: @order.updated_by.nick += raw t '.text0', ordergroup: @group_order.ordergroup.name, order: @order.name, when: I18n.l(@order.ends), user: show_user(@order.updated_by) - for group_order_article in @group_order.group_order_articles.ordered.all(:include => :order_article) - article = group_order_article.order_article.article \- #{article.name}: #{group_order_article.result} x #{article.unit} = #{group_order_article.result * article.fc_price} diff --git a/app/views/mailer/reset_password.text.haml b/app/views/mailer/reset_password.text.haml index fd836232..2582d317 100644 --- a/app/views/mailer/reset_password.text.haml +++ b/app/views/mailer/reset_password.text.haml @@ -1 +1 @@ -= raw t '.text', user: @user.nick, link: @link, expires: I18n.l(@user.reset_password_expires) += raw t '.text', user: show_user(@user), link: @link, expires: I18n.l(@user.reset_password_expires) diff --git a/app/views/messages/new.haml b/app/views/messages/new.haml index 8541b996..5d3e0c89 100644 --- a/app/views/messages/new.haml +++ b/app/views/messages/new.haml @@ -36,7 +36,7 @@ = t '.list.mail', email: mail_to(FoodsoftConfig[:mailing_list_subscribe]) #recipients - = f.input :recipient_tokens, :input_html => { 'data-pre' => User.find_all_by_id(@message.recipients_ids).map { |u| u.token_attributes }.to_json } + = f.input :recipient_tokens, :input_html => { 'data-pre' => User.find_all_by_id(@message.recipients_ids).map(&:token_attributes).to_json } = f.input :group_id, :as => :select, :collection => Group.undeleted.order('type DESC, name ASC').all.reject { |g| g.memberships.empty? } = f.input :private = f.input :subject, input_html: {class: 'input-xxlarge'} diff --git a/app/views/orders/show.html.haml b/app/views/orders/show.html.haml index 82d43cc2..865a83c8 100644 --- a/app/views/orders/show.html.haml +++ b/app/views/orders/show.html.haml @@ -13,7 +13,7 @@ %dt= t '.note' %dd= @order.note %dt= t '.created_by' - %dd= link_to_user_message_if_valid(@order.created_by) + %dd= show_user_link(@order.created_by) %dt= t '.begin' %dd= format_time(@order.starts) %dt= t '.ending' diff --git a/app/views/sessions/new.html.haml b/app/views/sessions/new.html.haml index 09a45c39..76760654 100644 --- a/app/views/sessions/new.html.haml +++ b/app/views/sessions/new.html.haml @@ -12,12 +12,14 @@ = form_tag sessions_path, class: 'form-horizontal' do .control-group - %label(for='nick' class='control-label')= t '.user' + %label(for='nick' class='control-label') + = User.human_attribute_name (FoodsoftConfig[:use_nick] ? :user : :email) .controls = text_field_tag 'nick', nil, autocapitalize: 'off', autocorrect: 'off' .control-group - %label(for='password' class='control-label')= t '.password' + %label(for='password' class='control-label') + = User.human_attribute_name :password .controls = password_field_tag 'password', nil, autocapitalize: 'off', autocorrect: 'off' diff --git a/app/views/shared/_comments.haml b/app/views/shared/_comments.haml index 27da9138..03d2c0b3 100644 --- a/app/views/shared/_comments.haml +++ b/app/views/shared/_comments.haml @@ -1,5 +1,5 @@ - comments.each do |comment| .comment[comment] %strong= comment.user.try(:ordergroup_name) - %small (#{comment.user.try(:nick)} am #{format_time(comment.created_at)}): + %small (#{show_user comment.user} am #{format_time(comment.created_at)}): = simple_format(comment.text) diff --git a/app/views/shared/_group.html.haml b/app/views/shared/_group.html.haml index b9b914ce..ebd34405 100644 --- a/app/views/shared/_group.html.haml +++ b/app/views/shared/_group.html.haml @@ -12,7 +12,7 @@ %dd - members = group.users = "(#{members.size})" - = members.collect(&:nick).join(", ") + = members.collect{|u| show_user(u)}.join(", ") - unless group.is_a?(Workgroup) %dt= t '.apple_limit' %dd= group.ignore_apple_restriction ? t('.deactivated') : t('.activated') diff --git a/app/views/shared/_group_form_fields.html.haml b/app/views/shared/_group_form_fields.html.haml index 44376eaf..d8401aa4 100644 --- a/app/views/shared/_group_form_fields.html.haml +++ b/app/views/shared/_group_form_fields.html.haml @@ -4,7 +4,7 @@ = yield = f.input :user_tokens, :as => :string, - :input_html => { 'data-pre' => f.object.users.map { |u| u.token_attributes }.to_json } + :input_html => { 'data-pre' => f.object.users.map(&:token_attributes).to_json } - content_for :javascript do :javascript diff --git a/app/views/shared/_open_orders.html.haml b/app/views/shared/_open_orders.html.haml index e3fef854..7267e4b1 100644 --- a/app/views/shared/_open_orders.html.haml +++ b/app/views/shared/_open_orders.html.haml @@ -19,7 +19,7 @@ %td= format_time(order.ends) unless order.ends.nil? - if group_order = order.group_order(ordergroup) - total += group_order.price - %td= "#{group_order.updated_by.nick} (#{format_time(group_order.updated_on)})" + %td= "#{show_user group_order.updated_by} (#{format_time(group_order.updated_on)})" %td.numeric = link_to_ordering(order, show: true) do - number_to_currency(group_order.price) diff --git a/app/views/shared/_user_form_fields.html.haml b/app/views/shared/_user_form_fields.html.haml index bfd27f49..56701874 100644 --- a/app/views/shared/_user_form_fields.html.haml +++ b/app/views/shared/_user_form_fields.html.haml @@ -1,4 +1,6 @@ -= f.input :nick +- if FoodsoftConfig[:use_nick] + -# use_nil option to user model validators break required mark + = f.input :nick, required: true = f.input :first_name = f.input :last_name = f.input :email @@ -19,7 +21,8 @@ = t 'simple_form.labels.settings.settings_group.privacy' = profile.input 'phone_is_public', as: :boolean, label: false, input_html: { checked: f.object.settings.profile['phone_is_public'] } = profile.input 'email_is_public', as: :boolean, label: false, input_html: { checked: f.object.settings.profile['email_is_public'] } - = profile.input 'name_is_public', as: :boolean, label: false, input_html: { checked: f.object.settings.profile['name_is_public'] } + - if FoodsoftConfig[:use_nick] + = profile.input 'name_is_public', as: :boolean, label: false, input_html: { checked: f.object.settings.profile['name_is_public'] } .settings-group %div{class: 'control-group'} diff --git a/app/views/shared/_workgroup_members.haml b/app/views/shared/_workgroup_members.haml index 960113d8..ac8fabd3 100644 --- a/app/views/shared/_workgroup_members.haml +++ b/app/views/shared/_workgroup_members.haml @@ -8,7 +8,8 @@ %div{id: "collapse#{workgroup.id}", class: 'accordion-body collapse'} .accordion-inner %ul.unstyled - - workgroup.users.includes(:groups).order('nick').each do |user| + - workgroup.users.includes(:groups).natural_order.each do |user| %li - = user.nick + = show_user(user) %small (#{user.ordergroup.try(:name)}) + diff --git a/app/views/stock_takings/new.html.haml b/app/views/stock_takings/new.html.haml index 51239ba4..481ffdc6 100644 --- a/app/views/stock_takings/new.html.haml +++ b/app/views/stock_takings/new.html.haml @@ -7,7 +7,7 @@ = simple_form_for(@stock_taking) do |f| = f.input :date, as: :date_picker - = f.input :note, :input_html => {:size => "28x7", :value => "#{@current_user.nick}: ..."} + = f.input :note, :input_html => {:size => "28x7", :value => "#{show_user @current_user, unique: true}: ..."} %h2= t '.stock_articles' #stock_changes diff --git a/app/views/tasks/_form.html.haml b/app/views/tasks/_form.html.haml index 95f3b134..78925c41 100644 --- a/app/views/tasks/_form.html.haml +++ b/app/views/tasks/_form.html.haml @@ -19,7 +19,7 @@ = f.input :name = f.input :description, as: :text, input_html: {rows: 10} = f.input :duration, :as => :select, :collection => 1..3 - = f.input :user_list, :as => :string, :input_html => { 'data-pre' => @task.users.map { |u| u.token_attributes }.to_json } + = f.input :user_list, :as => :string, :input_html => { 'data-pre' => @task.users.map(&:token_attributes).to_json } = f.input :required_users = f.association :workgroup = f.input :due_date, as: :date_picker diff --git a/config/app_config.yml.SAMPLE b/config/app_config.yml.SAMPLE index 594b9c70..03628c49 100644 --- a/config/app_config.yml.SAMPLE +++ b/config/app_config.yml.SAMPLE @@ -52,6 +52,11 @@ default: &defaults # not fully enforced right now, since the check is only client-side # minimum_balance: 0 + # When use_nick is enabled, there will be a nickname field in the user form, + # and the option to show a nickname instead of full name to foodcoop members. + # Members of a user's groups and administrators can still see full names. + use_nick: false + # email address to be used as sender email_sender: foodsoft@foodcoop.test diff --git a/config/locales/de.yml b/config/locales/de.yml index 669ea57a..6c776a12 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -1328,9 +1328,7 @@ de: login: Anmelden nojs: Achtung, Cookies und Javascript müssen aktiviert sein! %{link} bitte abschalten. noscript: NoScript - password: Passwort title: Foodsoft anmelden - user: Benutzerin shared: articles: ordered: Bestellt diff --git a/config/locales/en.yml b/config/locales/en.yml index 3b8ff87f..5d3b1e06 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1284,7 +1284,7 @@ en: headings: Heading italic: italic list_item_1: First list item - list_item_2: Secound list item + list_item_2: Second list item noformat: No wiki-formatting ordered_list: Numbered list section_block: Block formatting @@ -1332,9 +1332,7 @@ en: login: Login nojs: Attention, cookies and javascript have to be activated! Please switch off %{link}. noscript: NoScript - password: Password title: Foodsoft login - user: User shared: articles: ordered: Ordered diff --git a/config/locales/fr.yml b/config/locales/fr.yml index f8aaada7..f5e54531 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -1335,9 +1335,7 @@ fr: login: Te connecter nojs: Attention, les cookies et le javascript doivent être activés! Merci de désactiver %{link}. noscript: NoScript - password: Mot de passe title: Te connecter à Foodsoft - user: Identifiant shared: articles: ordered: Commandé diff --git a/config/locales/nl.yml b/config/locales/nl.yml index b8a55aca..eb12b8d5 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -58,8 +58,8 @@ nl: note: Notitie starts: Start op order_article: - units_to_order: - update_current_price: + units_to_order: Aantal eenheden + update_current_price: Huidige prijs overal bijwerken order_comment: text: Commentaar voor deze bestelling toevoegen ... ordergroup: @@ -67,12 +67,12 @@ nl: contact_person: Contactpersoon contact_phone: Telefoon description: Omschrijving - ignore_apple_restriction: + ignore_apple_restriction: Bestelstop vanwege appelpunten negeren name: Naam user_tokens: Leden page: body: Bericht - parent_id: + parent_id: Ouderpagina title: Titel stock_article: price: Prijs @@ -354,10 +354,10 @@ nl: error_nosel: Je hebt geen artikelen geselecteerd parse_upload: body:

Ingelezen artikelen graag controleren.

Let op, momenteel vind er geen controle op dubbele artikelen plaats.

- title: + title: Artikelen uploaden sync: outlist: - alert_used: + alert_used: Opgelet, %{article} wordt gebruikt in een lopende bestelling. Haal het eerst uit de bestelling. body: ! 'De volgende artikelen zijn uit de lijst gehaald en worden verwijderd:' body_skip: Er zijn geen artikelen om te verwijderen. title: Uit de lijst halen ... @@ -382,7 +382,7 @@ nl: title: Artikelen uploaden voor %{supplier} deliveries: add_stock_change: - how_many_units: + how_many_units: ! 'Hoeveel eenheden (%{unit}) leveren? Voorraadartikel: %{name}.' create: notice: Levering is aangemaakt. Vergeet niet een factuur te maken! create_stock_article: @@ -390,22 +390,22 @@ nl: destroy: notice: Levering is verwijdered. edit: - title: + title: Levering aanpassen form: - actions: + actions: Taken article: Artikel category: Categorie create_from_blank: Nieuwe artikel invoeren - create_stock_article: - price: - quantity: - title_fill_quantities: - title_finish_delivery: - title_select_stock_articles: - unit: + create_stock_article: Voorraadartikel maken + price: Netto prijs + quantity: Hoeveelheid + title_fill_quantities: 2. Hoeveel mag er geleverd worden + title_finish_delivery: 3. Levering afmaken + title_select_stock_articles: 1. Kies voorraadartikelen + unit: Eenheid index: - confirm_delete: - new_delivery: + confirm_delete: Zeker weten? + new_delivery: Nieuwe levering maken voor %{supplier} title: invoice_amount: invoice_net_amount: @@ -429,12 +429,12 @@ nl: stock_article_form: copy_stock_article: stock_change_fields: - remove_article: - suppliers_overview: + remove_article: Artikel uit levering halen + suppliers_overview: Leverancieroverzicht update: notice: Levering is bijgewerkt. update_stock_article: - notice: + notice: Voorraadartikel "%{name}" is bijgewerkt. documents: order_by_articles: filename: Bestelling %{name}-%{date} - Artikellijst @@ -483,8 +483,8 @@ nl: new: first_paragraph: Probleem gevonden? Voorstel? Idee? Verbeterpunt? We horen graag je feedback. second_paragraph: - send: - title: + send: Verzenden + title: Feedback geven finance: balancing: close: @@ -555,7 +555,7 @@ nl: no_closed_orders: Momenteel zijn er geen gesloten bestellingen. state: Status summary: - changed: + changed: Waarden zijn gewijzigd! duration: Van %{starts} tot %{ends} fc_amount: ! 'FC-bedrag:' fc_profit: FC Winst @@ -603,7 +603,7 @@ nl: group_order_articles: form: amount_change_for: - result_hint: + result_hint: ! 'Eenheid: %{unit}' index: amount: Bedrag amount_fc: Bedrag(FC) @@ -684,7 +684,7 @@ nl: title: Werkgroepen workgroup: edit: Groep bewerken - show_tasks: + show_tasks: Alle taken weergeven group_orders: archive: desc: Bekijk hier alle %{link}. @@ -716,7 +716,7 @@ nl: note: Notitie price: Prijs reset_article_search: - search_article: + search_article: Artikel zoeken... sum: Som sum_amount: ! 'Huidig totaalbedrag:' supplier: Leverancier @@ -949,11 +949,11 @@ nl: dateformat: ! '%d %b' feedback: header: ! '%{user} schreef op %{date}:' - subject: + subject: Feedback van %{email} foodsoft_message: footer: invite: - subject: + subject: Uitnodiging voor de foodcoop text: negative_balance: subject: @@ -1009,21 +1009,21 @@ nl: create: notice: Bericht is opgeslagen en wordt verzonden. index: - new: - title: + new: Nieuw bericht + title: Berichten messages: - reply: + reply: Antwoorden model: - reply_header: - reply_indent: - reply_subject: + reply_header: ! '%{user} schreef op %{when}:' + reply_indent: ! '> %{line}' + reply_subject: ! 'Re: %{subject}' new: list: - desc: + desc: ! 'Berichten voor alle leden graag via de mailing-lijst verzenden: %{list}' mail: bijvoorbeeld door een email te sturen naar %{email}. - subscribe: - subscribe_msg: - wiki: + subscribe: Lees meer over de mailing-lijst op %{link}. + subscribe_msg: Mogelijk moet je je eerst aanmelden voor de mailing-lijst. + wiki: Wiki (mailing-lijst pagina) no_user_found: Geen gebruiker gevonden search: Zoeken ... search_user: Gebruiker zoeken @@ -1152,28 +1152,30 @@ nl: show: action_end: Sluiten! amounts: - articles: - articles_ordered: - begin: + articles: Artikeloverzicht + articles_ordered: ! 'Bestelde artikelen:' + begin: ! 'Begin:' comments: - title: - comments_link: + title: Commentaar + comments_link: Commentaar confirm_delete: - confirm_end: - created_by: + confirm_end: ! 'Wil je de bestelling %{order} echt sluiten? + + Hierna kan zij niet opnieuw geopend worden.' + created_by: ! 'Geopend door:' download: - article_pdf: - download_file: - fax_pdf: - fax_txt: - group_pdf: - matrix_pdf: - title: - ending: - group_orders: - note: - sort_article: - sort_group: + article_pdf: Artikelen PDF + download_file: Bestand downloaden + fax_pdf: Fax PDF + fax_txt: Fax text + group_pdf: Huishoudens PDF + matrix_pdf: Matrix PDF + title: Downloaden + ending: ! 'Einde:' + group_orders: ! 'Ledenbestellingen:' + note: ! 'Notitie:' + sort_article: Gesorteerd naar artikel + sort_group: Gesorteerd naar huishouden supplier: title: warn_not_closed: Opgelet, bestelling is nog niet afgerekend. @@ -1213,17 +1215,17 @@ nl: heading: headings: italic: - list_item_1: - list_item_2: - noformat: - ordered_list: - section_block: - section_character: - section_link: - section_table: - see_tables: - tables_link: - text: + list_item_1: Eerste in de lijst + list_item_2: Tweede in de lijst + noformat: Zonder wiki-opmaak + ordered_list: Genummerde lijst + section_block: Paragrafen + section_character: Tekens + section_link: Links + section_table: Tabellen + see_tables: zie %{tables_link} + tables_link: Tabellen + text: tekst title: unordered_list: wiki_link_ex: @@ -1262,9 +1264,7 @@ nl: login: Aanmelden nojs: Opgelet, cookies en javascript moeten toegelaten worden! %{link} uitzetten, alsjeblieft. noscript: NoScript - password: Wachtwoord title: Foodsoft aanmelden - user: Gebruiker shared: articles: ordered: Besteld diff --git a/db/migrate/20130920201529_allow_missing_nick.rb b/db/migrate/20130920201529_allow_missing_nick.rb new file mode 100644 index 00000000..f5b96d3e --- /dev/null +++ b/db/migrate/20130920201529_allow_missing_nick.rb @@ -0,0 +1,9 @@ +class AllowMissingNick < ActiveRecord::Migration + def self.up + change_column :users, :nick, :string, :default => nil, :null => true + end + + def self.down + change_column :users, :nick, :string, :default => "", :null => false + end +end diff --git a/db/schema.rb b/db/schema.rb index 0d5b1326..4170d918 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20130718183101) do +ActiveRecord::Schema.define(:version => 20130920201529) do create_table "article_categories", :force => true do |t| t.string "name", :default => "", :null => false @@ -324,7 +324,7 @@ ActiveRecord::Schema.define(:version => 20130718183101) do add_index "tasks", ["workgroup_id"], :name => "index_tasks_on_workgroup_id" create_table "users", :force => true do |t| - t.string "nick", :default => "", :null => false + t.string "nick" t.string "password_hash", :default => "", :null => false t.string "password_salt", :default => "", :null => false t.string "first_name", :default => "", :null => false diff --git a/lib/foodsoft_config.rb b/lib/foodsoft_config.rb index 71b64024..ca8952e7 100644 --- a/lib/foodsoft_config.rb +++ b/lib/foodsoft_config.rb @@ -9,6 +9,8 @@ class FoodsoftConfig set_config Rails.env # Overwrite scope to have a better namescope than 'production' self.scope = config[:default_scope] or raise "No default_scope is set" + # Set defaults for backward-compatibility + set_missing end # Set config and database connection for specific foodcoop @@ -46,5 +48,13 @@ class FoodsoftConfig ActiveRecord::Base.establish_connection(database_config) end + # When new options are introduced, put backward-compatible defaults here, so that + # configuration files that haven't been updated, still work as they did. + def set_missing + config.replace({ + use_nick: true + }.merge(config)) + end + end -end \ No newline at end of file +end diff --git a/lib/foodsoft_wiki/app/views/pages/_page_list_item.html.haml b/lib/foodsoft_wiki/app/views/pages/_page_list_item.html.haml index 496e0720..cfd03a59 100644 --- a/lib/foodsoft_wiki/app/views/pages/_page_list_item.html.haml +++ b/lib/foodsoft_wiki/app/views/pages/_page_list_item.html.haml @@ -2,7 +2,7 @@ %tr %td{:style => "padding-left: #{ident}px"} = link_to page.title, wiki_page_path(page.permalink) - %td #{page.user.try(:nick)} (#{format_datetime_timespec(page.updated_at, t('.date_format'))}) + %td #{show_user page.user} (#{format_datetime_timespec(page.updated_at, t('.date_format'))}) -if siteMap == 1 -for child in page.children.all = render :partial => 'page_list_item', :locals => {:page => child, :level => level+1, :siteMap => 1} diff --git a/lib/foodsoft_wiki/app/views/pages/show.html.haml b/lib/foodsoft_wiki/app/views/pages/show.html.haml index 2c1d0bb1..91b7a9fc 100644 --- a/lib/foodsoft_wiki/app/views/pages/show.html.haml +++ b/lib/foodsoft_wiki/app/views/pages/show.html.haml @@ -17,7 +17,7 @@ - @page.versions.reverse.each do |version| %li = link_to I18n.l(version.updated_at, :format => t('.date_format')), version_page_path(@page, :version => version.lock_version) - = "(#{User.find_by_id(version.updated_by).try(:nick)})" + = "(#{show_user(User.find_by_id(version.updated_by))})" - unless @page.children.empty? #subpages.well.well-small{:style => "display:none"} @@ -48,4 +48,4 @@ %i.icon-edit= t '.edit' = link_to t('.delete'), @page, class: 'btn btn-danger', :method => :delete, :confirm => t('.delete_confirm') - != '| ' + t('.last_updated', user: h(@page.user.try(:nick)), when: format_datetime(@page.updated_at)) + != '| ' + t('.last_updated', user: show_user(@page.user), when: format_datetime(@page.updated_at)) diff --git a/lib/foodsoft_wiki/app/views/pages/version.html.haml b/lib/foodsoft_wiki/app/views/pages/version.html.haml index 222b465d..864c4f28 100644 --- a/lib/foodsoft_wiki/app/views/pages/version.html.haml +++ b/lib/foodsoft_wiki/app/views/pages/version.html.haml @@ -4,7 +4,7 @@ %h3= t '.title_version' %b= "#{format_datetime_timespec(@version.updated_at, t('.date_format'))}" %ul - %li= t '.author', user: User.find(@version.updated_by).nick + %li= t '.author', user: show_user(User.find(@version.updated_by)) %li= link_to t('.view_current'), wiki_page_path(:permalink => @page.permalink) %li= link_to t('.revert'), revert_page_path(@page, :version => @version.lock_version) diff --git a/lib/foodsoft_wiki/config/locales/en.yml b/lib/foodsoft_wiki/config/locales/en.yml new file mode 100644 index 00000000..c41d6759 --- /dev/null +++ b/lib/foodsoft_wiki/config/locales/en.yml @@ -0,0 +1,85 @@ +en: + activerecord: + attributes: + page: + body: Body + parent_id: Parent page + title: Title + model: + page: + redirect: Redirect to [[%{title}]]... + navigation: + wiki: + all_pages: All Pages + home: Home + title: Wiki + pages: + all: + new_page: Create new page + recent_changes: Recent changes + search: + action: Search + placeholder: Page title .. + site_map: Sitemap + title: All Wiki pages + title_list: List of pages + body: + title_toc: Content + create: + notice: Page was created + cshow: + error_noexist: Page doesn’t exist! + redirect_notice: Redirected from %{page} ... + destroy: + notice: The page '%{page}' and all subpages have been deleted successfully. + edit: + title: Edit page + error_stale_object: Warning, the page has just been edited by someone else. Please try again. + form: + help: + bold: bold + external_link_ex: External page + external_links: External links + heading: level %{level} + headings: Heading + italic: italic + list_item_1: First list item + list_item_2: Second list item + noformat: No wiki-formatting + ordered_list: Numbered list + section_block: Block formatting + section_character: Character formatting + section_link: Link formatting + section_table: Table formatting + see_tables: see %{tables_link} + tables_link: Tables + text: text + title: Quick formatting help + unordered_list: Item list + wiki_link_ex: Foodsoft Wiki Page + wiki_links: Wiki-links + preview: Preview + last_updated: Last updated + new: + title: Create new wiki page + page_list_item: + date_format: ! '%a, %d %B %Y %H:%M:%S' + show: + date_format: ! '%d-%m-%y %H:%M' + delete: Delete page + delete_confirm: ! 'Warning: all subpages will be deleted as well. Are you sure?' + edit: Edit page + last_updated: Last updated by %{user} on %{when} + subpages: subpages + title_versions: Versions + versions: Versions (%{count}) + title: Title + update: + notice: Page was updated + version: + author: ! 'Author: %{user}' + date_format: ! '%a, %d-%m-%Y, %H:%M' + revert: Revert to this version + title: ! '%{title} - version %{version}' + title_version: Version + view_current: See current version diff --git a/spec/integration/session_spec.rb b/spec/integration/session_spec.rb index d6942e94..aa71972d 100644 --- a/spec/integration/session_spec.rb +++ b/spec/integration/session_spec.rb @@ -4,7 +4,7 @@ describe 'the session', :type => :feature do let(:user) { create :user } describe 'login page', :type => :feature do - it 'is accesible' do + it 'is accessible' do get login_path expect(response).to be_success end @@ -16,6 +16,13 @@ describe 'the session', :type => :feature do login user.nick, 'XX'+user.password expect(page).to have_selector('.alert-error') end + it 'can log me in using an email address' do + visit login_path + fill_in 'nick', :with => user.email + fill_in 'password', :with => user.password + find('input[type=submit]').click + expect(page).to_not have_selector('.alert-error') + end end end diff --git a/spec/models/article_spec.rb b/spec/models/article_spec.rb index e3bab788..bd0d991c 100644 --- a/spec/models/article_spec.rb +++ b/spec/models/article_spec.rb @@ -52,4 +52,58 @@ describe Article do order = create :order, supplier: supplier, article_ids: [article.id] expect(article.in_open_order).to eq(order) end + + + it 'has no shared article by default' do + expect(article.shared_article).to be_nil + end + + describe 'connected to a shared database', :type => :feature do + let(:shared_supplier) { create(:supplier) } + let(:shared_article) { create :article, supplier: shared_supplier, order_number: Faker::Lorem.characters(rand(1..12)) } + let(:supplier) { create :supplier, shared_supplier_id: shared_supplier.id } + let(:article) { create :article, supplier: supplier, order_number: shared_article.order_number } + + it 'can be found in the shared database' do + expect(article.shared_article).to_not be_nil + end + + it 'can find updates' do + changed = article.shared_article_changed? + expect(changed).to_not be_false + expect(changed.length).to be > 1 + end + + it 'can be synchronised' do + # TODO move article sync from supplier to article + article # need to reference for it to exist when syncing + updated_article = supplier.sync_all[0].select{|s| s[0].id==article.id}.first[0] + article.update_attributes updated_article.attributes.reject{|k,v| k=='id' or k=='type'} + expect(article.name).to eq(shared_article.name) + # now synchronising shouldn't change anything anymore + expect(article.shared_article_changed?).to be_false + end + + it 'does not need to synchronise an imported article' do + article = SharedArticle.find(shared_article.id).build_new_article(supplier) + expect(article.shared_article_changed?).to be_false + end + + it 'adapts to foodcoop units when synchronising' do + shared_article.unit = '1kg' + shared_article.unit_quantity = 1 + shared_article.save! + article = SharedArticle.find(shared_article.id).build_new_article(supplier) + article.article_category = create :article_category + article.unit = '200g' + article.shared_updated_on -= 1 # to make update do something + article.save! + # TODO get sync functionality in article + updated_article = supplier.sync_all[0].select{|s| s[0].id==article.id}.first[0] + article.update_attributes! updated_article.attributes.reject{|k,v| k=='id' or k=='type'} + expect(article.unit).to eq '200g' + expect(article.unit_quantity).to eq 5 + expect(article.price).to be_within(1e-3).of(shared_article.price/5) + end + end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index bc90fa01..fec01465 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -49,6 +49,16 @@ describe User do it 'has a unique email' do expect(build(:user, email: "#{user.email}")).to be_invalid end + + it 'can authenticate using email address' do + expect(User.authenticate(user.email, 'blahblah')).to be_true + end + + it 'can authenticate when there is no nick' do + user.nick = nil + expect(user).to be_valid + expect(User.authenticate(user.email, 'blahblah')).to be_true + end end describe 'admin' do diff --git a/spec/support/shared_database.rb b/spec/support/shared_database.rb new file mode 100644 index 00000000..55f8f2b3 --- /dev/null +++ b/spec/support/shared_database.rb @@ -0,0 +1,29 @@ +# http://stackoverflow.com/questions/8774227 +# http://blog.plataformatec.com.br/2011/12/three-tips-to-improve-the-performance-of-your-test-suite +class ActiveRecord::Base + mattr_accessor :shared_connection + @@shared_connection = nil + + def self.connection + @@shared_connection || retrieve_connection + end +end +# Forces all threads to share the same connection. This works on +# Capybara because it starts the web server in a thread. +ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection + +ActiveSupport.on_load(:after_initialize) do + # We simulate the shared database by pointing to our own database. + # This allows running tests without additional database setup. + # But take care when designing tests using the shared database. + SharedSupplier.establish_connection Rails.env + SharedArticle.establish_connection Rails.env + # hack for different structure of shared database + SharedArticle.class_eval do + alias_attribute :number, :order_number + alias_attribute :updated_on, :updated_at + def self.find_by_number(n) + find_by_order_number(n) + end + end +end