Merge remote-tracking branch 'foodcoops/master' into feature-receive
This commit is contained in:
commit
27a73be68f
16 changed files with 87 additions and 32 deletions
|
@ -126,6 +126,15 @@ $(function() {
|
||||||
$(this).children('input[type="submit"]').attr('disabled', 'disabled');
|
$(this).children('input[type="submit"]').attr('disabled', 'disabled');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// The autocomplete attribute is used for both autocompletion and storing
|
||||||
|
// for passwords, it's nice to store it when editing one's own profile,
|
||||||
|
// but never autocomplete. Only implemented for passwords.
|
||||||
|
$('input[type="password"][autocomplete="off"][data-store="on"]').each(function() {
|
||||||
|
$(this).on('change', function() {
|
||||||
|
$(this).removeAttr('autocomplete');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Use bootstrap datepicker for dateinput
|
// Use bootstrap datepicker for dateinput
|
||||||
$('.datepicker').datepicker({format: 'yyyy-mm-dd', language: I18n.locale});
|
$('.datepicker').datepicker({format: 'yyyy-mm-dd', language: I18n.locale});
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ class ApplicationController < ActionController::Base
|
||||||
helper_method :available_locales
|
helper_method :available_locales
|
||||||
|
|
||||||
protect_from_forgery
|
protect_from_forgery
|
||||||
before_filter :select_foodcoop, :authenticate, :store_controller, :items_per_page, :set_redirect_to
|
before_filter :select_foodcoop, :authenticate, :store_controller, :items_per_page
|
||||||
after_filter :remove_controller
|
after_filter :remove_controller
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,8 +80,8 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
# checks if the current_user is member of given group.
|
# checks if the current_user is member of given group.
|
||||||
# if fails the user will redirected to startpage
|
# if fails the user will redirected to startpage
|
||||||
def authenticate_membership_or_admin
|
def authenticate_membership_or_admin(group_id = params[:id])
|
||||||
@group = Group.find(params[:id])
|
@group = Group.find(group_id)
|
||||||
unless @group.member?(@current_user) or @current_user.role_admin?
|
unless @group.member?(@current_user) or @current_user.role_admin?
|
||||||
redirect_to root_path, alert: I18n.t('application.controller.error_members_only')
|
redirect_to root_path, alert: I18n.t('application.controller.error_members_only')
|
||||||
end
|
end
|
||||||
|
@ -128,18 +128,6 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_redirect_to
|
|
||||||
session[:redirect_to] = params[:redirect_to] if params[:redirect_to]
|
|
||||||
end
|
|
||||||
|
|
||||||
def back_or_default_path(default = root_path)
|
|
||||||
if session[:redirect_to].present?
|
|
||||||
default = session[:redirect_to]
|
|
||||||
session[:redirect_to] = nil
|
|
||||||
end
|
|
||||||
default
|
|
||||||
end
|
|
||||||
|
|
||||||
# Always stay in foodcoop url scope
|
# Always stay in foodcoop url scope
|
||||||
def default_url_options(options = {})
|
def default_url_options(options = {})
|
||||||
{foodcoop: FoodsoftConfig.scope}
|
{foodcoop: FoodsoftConfig.scope}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
class InvitesController < ApplicationController
|
class InvitesController < ApplicationController
|
||||||
|
|
||||||
before_filter :authenticate_membership_or_admin, :only => [:new]
|
before_filter :authenticate_membership_or_admin_for_invites
|
||||||
#TODO: authorize also for create action.
|
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@invite = Invite.new(:user => @current_user, :group => @group)
|
@invite = Invite.new(:user => @current_user, :group => @group)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authenticate_membership_or_admin params[:invite][:group_id]
|
||||||
@invite = Invite.new(params[:invite])
|
@invite = Invite.new(params[:invite])
|
||||||
if @invite.save
|
if @invite.save
|
||||||
Mailer.invite(@invite).deliver
|
Mailer.invite(@invite).deliver
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html do
|
||||||
redirect_to back_or_default_path, notice: I18n.t('invites.success')
|
redirect_to root_path, notice: I18n.t('invites.success')
|
||||||
end
|
end
|
||||||
format.js { render layout: false }
|
format.js { render layout: false }
|
||||||
end
|
end
|
||||||
|
@ -23,4 +23,10 @@ class InvitesController < ApplicationController
|
||||||
render action: :new
|
render action: :new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def authenticate_membership_or_admin_for_invites
|
||||||
|
authenticate_membership_or_admin((params[:invite][:group_id] rescue params[:id]))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
13
app/helpers/shared_helper.rb
Normal file
13
app/helpers/shared_helper.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
module SharedHelper
|
||||||
|
|
||||||
|
# provide input_html for password autocompletion
|
||||||
|
def autocomplete_flag_to_password_html(password_autocomplete)
|
||||||
|
case password_autocomplete
|
||||||
|
when true then {autocomplete: 'on'}
|
||||||
|
when false then {autocomplete: 'off'}
|
||||||
|
when 'store-only' then {autocomplete: 'off', data: {store: 'on'}}
|
||||||
|
else {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -73,8 +73,15 @@ class User < ActiveRecord::Base
|
||||||
|
|
||||||
# search by (nick)name
|
# search by (nick)name
|
||||||
def self.natural_search(q)
|
def self.natural_search(q)
|
||||||
# we always use both nick and name, to make sure a user is found
|
q = q.strip
|
||||||
where("CONCAT(first_name, CONCAT(' ', last_name)) LIKE :q OR nick LIKE :q", q: "%#{q}%")
|
users = User.arel_table
|
||||||
|
# full string as nickname
|
||||||
|
match_nick = users[:nick].matches("%#{q}%")
|
||||||
|
# or each word matches either first or last name
|
||||||
|
match_name = q.split.map do |a|
|
||||||
|
users[:first_name].matches("%#{a}%").or users[:last_name].matches("%#{a}%")
|
||||||
|
end.reduce(:and)
|
||||||
|
User.where(match_nick.or match_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def locale
|
def locale
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
= simple_form_for([:admin, @user]) do |f|
|
= simple_form_for([:admin, @user]) do |f|
|
||||||
= render 'shared/user_form_fields', f: f
|
= render 'shared/user_form_fields', f: f, password_autocomplete: false
|
||||||
.form-actions
|
.form-actions
|
||||||
= f.submit
|
= f.submit
|
||||||
= link_to t('ui.or_cancel'), :back
|
= link_to t('ui.or_cancel'), :back
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
- if @invoice.delivery
|
- if @invoice.delivery
|
||||||
%p= t('finance.invoices.linked', what_link: link_to(t('finance.invoices.linked_delivery'), [@invoice.supplier,@invoice.delivery])).html_safe
|
%p= t('finance.invoices.linked', what_link: link_to(t('finance.invoices.linked_delivery'), [@invoice.supplier,@invoice.delivery])).html_safe
|
||||||
- if @invoice.order
|
- if @invoice.order
|
||||||
%p= t('finance.invoices.linked', what_link: link_to(t('finance.invoices.linked_order'), @invoice.order)).html_safe
|
%p= t('finance.invoices.linked', what_link: link_to(t('finance.invoices.linked_order'), new_finance_order_path(order_id: @invoice.order.id))).html_safe
|
||||||
|
|
||||||
= f.association :supplier, hint: false
|
= f.association :supplier, hint: false
|
||||||
= f.input :number
|
= f.input :number
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
= h(t('.user.title', user: show_user))
|
= h(t('.user.title', user: show_user))
|
||||||
%small= t '.user.since', when: distance_of_time_in_words(Time.now, @current_user.created_on)
|
%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|
|
= simple_form_for(@current_user, :url => update_profile_path) do |f|
|
||||||
= render :partial => 'shared/user_form_fields', :locals => {:f => f}
|
= render :partial => 'shared/user_form_fields', :locals => {:f => f, :password_autocomplete => 'store-only'}
|
||||||
.form-actions
|
.form-actions
|
||||||
= submit_tag t('ui.save'), class: 'btn'
|
= submit_tag t('ui.save'), class: 'btn'
|
||||||
.span5
|
.span5
|
||||||
|
|
|
@ -25,15 +25,15 @@
|
||||||
- if FoodsoftConfig[:mailing_list].blank?
|
- if FoodsoftConfig[:mailing_list].blank?
|
||||||
= f.input :sent_to_all, :as => :boolean
|
= f.input :sent_to_all, :as => :boolean
|
||||||
- else
|
- else
|
||||||
%b= t '.list.desc', list: mail_to(FoodsoftConfig[:mailing_list])
|
%b= t('.list.desc', list: mail_to(FoodsoftConfig[:mailing_list])).html_safe
|
||||||
%br/
|
%br/
|
||||||
%small{:style => "color:grey"}
|
%small{:style => "color:grey"}
|
||||||
= t '.list.subscribe_msg'
|
= t '.list.subscribe_msg'
|
||||||
%br/
|
%br/
|
||||||
- if FoodsoftConfig[:mailing_list_subscribe].blank?
|
- if FoodsoftConfig[:mailing_list_subscribe].blank?
|
||||||
= t '.list.subscribe', link: link_to(t('.list.wiki'), wiki_page_path('MailingListe'))
|
= t('.list.subscribe', link: link_to(t('.list.wiki'), wiki_page_path('MailingListe'))).html_safe
|
||||||
- else
|
- else
|
||||||
= t '.list.mail', email: mail_to(FoodsoftConfig[:mailing_list_subscribe])
|
= t('.list.mail', email: mail_to(FoodsoftConfig[:mailing_list_subscribe])).html_safe
|
||||||
|
|
||||||
#recipients
|
#recipients
|
||||||
= f.input :recipient_tokens, :input_html => { 'data-pre' => User.find_all_by_id(@message.recipients_ids).map(&: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 }
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
- 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 :first_name
|
||||||
= f.input :last_name
|
= f.input :last_name
|
||||||
= f.input :email
|
= f.input :email
|
||||||
|
-# need :required because :use_nil option on user model validators break the required mark
|
||||||
|
= f.input :nick, required: true if FoodsoftConfig[:use_nick]
|
||||||
|
-# You can control password autocompletion by passing `password_autocomplete` to this partial.
|
||||||
|
-# Possible values: undefined/nil, true, false, 'store-only'
|
||||||
|
-# see also https://github.com/foodcoops/foodsoft/wiki/Form-autocompletion
|
||||||
|
- password_autocomplete = nil unless defined?(:password_autocomplete)
|
||||||
|
- password_html = autocomplete_flag_to_password_html(password_autocomplete)
|
||||||
|
= f.input :password, :required => f.object.new_record?, input_html: password_html
|
||||||
|
= f.input :password_confirmation, :required => f.object.new_record?, input_html: password_html
|
||||||
= f.input :phone
|
= f.input :phone
|
||||||
= f.input :password, :required => f.object.new_record?
|
|
||||||
= f.input :password_confirmation
|
|
||||||
|
|
||||||
= f.simple_fields_for :settings_attributes do |s|
|
= f.simple_fields_for :settings_attributes do |s|
|
||||||
= s.simple_fields_for :profile, defaults: { inline_label: true } do |profile|
|
= s.simple_fields_for :profile, defaults: { inline_label: true } do |profile|
|
||||||
|
|
|
@ -27,6 +27,11 @@ de:
|
||||||
article_category:
|
article_category:
|
||||||
description: Beschreibung
|
description: Beschreibung
|
||||||
name: Name
|
name: Name
|
||||||
|
article_price:
|
||||||
|
deposit: Pfand
|
||||||
|
price: Nettopreis
|
||||||
|
tax: MwSt
|
||||||
|
unit_quantity: Gebindegröße
|
||||||
delivery:
|
delivery:
|
||||||
delivered_on: Lieferdatum
|
delivered_on: Lieferdatum
|
||||||
note: Notiz
|
note: Notiz
|
||||||
|
@ -1167,6 +1172,7 @@ de:
|
||||||
title_list: Seiten-Liste
|
title_list: Seiten-Liste
|
||||||
body:
|
body:
|
||||||
title_toc: Inhalt
|
title_toc: Inhalt
|
||||||
|
wikicloth_exception: "Entschuldigung, ein Fehler ist beim Anzeigen der Wikiseite aufgetreten: »%{msg}«. Bearbeiten der Seite kann helfen, diesen Fehler zu beseitigen."
|
||||||
create:
|
create:
|
||||||
notice: Seite wurde angelegt
|
notice: Seite wurde angelegt
|
||||||
cshow:
|
cshow:
|
||||||
|
@ -1360,6 +1366,8 @@ de:
|
||||||
title: Lagerartikel kopieren
|
title: Lagerartikel kopieren
|
||||||
create:
|
create:
|
||||||
notice: Neuer Lagerartikel »%{name}« gespeichert.
|
notice: Neuer Lagerartikel »%{name}« gespeichert.
|
||||||
|
derive:
|
||||||
|
title: Lagerartikel aus Vorlage erstellen
|
||||||
destroy:
|
destroy:
|
||||||
notice: Artikel %{name} gelöscht.
|
notice: Artikel %{name} gelöscht.
|
||||||
edit:
|
edit:
|
||||||
|
|
|
@ -27,6 +27,11 @@ en:
|
||||||
article_category:
|
article_category:
|
||||||
description: Description
|
description: Description
|
||||||
name: Name
|
name: Name
|
||||||
|
article_price:
|
||||||
|
deposit: Deposit
|
||||||
|
price: Price (net)
|
||||||
|
tax: VAT
|
||||||
|
unit_quantity: Unit quantity
|
||||||
delivery:
|
delivery:
|
||||||
delivered_on: Delivery date
|
delivered_on: Delivery date
|
||||||
note: Note
|
note: Note
|
||||||
|
@ -1178,6 +1183,7 @@ en:
|
||||||
title_list: List of pages
|
title_list: List of pages
|
||||||
body:
|
body:
|
||||||
title_toc: Content
|
title_toc: Content
|
||||||
|
wikicloth_exception: "I'm sorry to report that an error occured when interpreting the wiki page: %{msg}. Please try to fix it, and save the page again."
|
||||||
create:
|
create:
|
||||||
notice: Page was created
|
notice: Page was created
|
||||||
cshow:
|
cshow:
|
||||||
|
@ -1371,6 +1377,8 @@ en:
|
||||||
title: Copy stock article
|
title: Copy stock article
|
||||||
create:
|
create:
|
||||||
notice: New stock article "%{name}" was created.
|
notice: New stock article "%{name}" was created.
|
||||||
|
derive:
|
||||||
|
title: Add stock article using template
|
||||||
destroy:
|
destroy:
|
||||||
notice: Article %{name} was deleted.
|
notice: Article %{name} was deleted.
|
||||||
edit:
|
edit:
|
||||||
|
|
|
@ -27,6 +27,11 @@ fr:
|
||||||
article_category:
|
article_category:
|
||||||
description: Description
|
description: Description
|
||||||
name: Nom
|
name: Nom
|
||||||
|
article_price:
|
||||||
|
deposit: Consigne
|
||||||
|
price: Prix net
|
||||||
|
tax: TVA
|
||||||
|
unit_quantity: Unités par lot
|
||||||
delivery:
|
delivery:
|
||||||
delivered_on: Date de réapprovisionnement
|
delivered_on: Date de réapprovisionnement
|
||||||
note:
|
note:
|
||||||
|
|
|
@ -27,6 +27,11 @@ nl:
|
||||||
article_category:
|
article_category:
|
||||||
description: Omschrijving
|
description: Omschrijving
|
||||||
name: Naam
|
name: Naam
|
||||||
|
article_price:
|
||||||
|
deposit: Statiegeld
|
||||||
|
price: Netto prijs
|
||||||
|
tax: BTW
|
||||||
|
unit_quantity: Groothandelseenheid
|
||||||
delivery:
|
delivery:
|
||||||
delivered_on: Leverdatum
|
delivered_on: Leverdatum
|
||||||
note: Notitie
|
note: Notitie
|
||||||
|
|
|
@ -4,6 +4,8 @@ module PagesHelper
|
||||||
def wikified_body(body, title = nil)
|
def wikified_body(body, title = nil)
|
||||||
render_opts = {:locale => I18n.locale} # workaround for wikicloth 0.8.0 https://github.com/nricciar/wikicloth/pull/59
|
render_opts = {:locale => I18n.locale} # workaround for wikicloth 0.8.0 https://github.com/nricciar/wikicloth/pull/59
|
||||||
WikiCloth.new({:data => body+"\n", :link_handler => Wikilink.new, :params => {:referer => title}}).to_html(render_opts).html_safe
|
WikiCloth.new({:data => body+"\n", :link_handler => Wikilink.new, :params => {:referer => title}}).to_html(render_opts).html_safe
|
||||||
|
rescue => e
|
||||||
|
"<span class='alert alert-error'>#{t('.wikicloth_exception', :msg => e)}</span>".html_safe # try the following with line breaks: === one === == two == = three =
|
||||||
end
|
end
|
||||||
|
|
||||||
def link_to_wikipage(page, text = nil)
|
def link_to_wikipage(page, text = nil)
|
||||||
|
|
Loading…
Reference in a new issue