add foodcoop configuration screen
This commit is contained in:
parent
dd3ac0971c
commit
7b000c39eb
20 changed files with 562 additions and 12 deletions
|
@ -140,6 +140,23 @@ table {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
// Navigation with embedded tabs
|
||||
.nav-tabs-with-heading {
|
||||
> li {
|
||||
line-height: 40px;
|
||||
margin-top: 16.5px;
|
||||
a { padding-bottom: 9px; }
|
||||
}
|
||||
> li.heading {
|
||||
> h1, > h2, > h3 {
|
||||
font-size: 31.5px;
|
||||
line-height: 40px;
|
||||
margin: 0;
|
||||
}
|
||||
margin: 10px 1em 5px 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Tasks ..
|
||||
.accepted {
|
||||
color: #468847;
|
||||
|
@ -324,6 +341,15 @@ table.table {
|
|||
}
|
||||
}
|
||||
|
||||
// inline (boolean) position after/before heading
|
||||
label {
|
||||
h1, h2, h3, h4 {
|
||||
input[type=checkbox] {
|
||||
margin: auto 0.3em auto 0.3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// it's a bit distracting
|
||||
.icon-asterisk {
|
||||
font-size: 80%;
|
||||
|
|
39
app/controllers/admin/configs_controller.rb
Normal file
39
app/controllers/admin/configs_controller.rb
Normal file
|
@ -0,0 +1,39 @@
|
|||
class Admin::ConfigsController < Admin::BaseController
|
||||
|
||||
before_action :get_tabs, only: [:show, :list]
|
||||
|
||||
def show
|
||||
@current_tab = @tabs.include?(params[:tab]) ? params[:tab] : @tabs.first
|
||||
@cfg = FoodsoftConfig
|
||||
end
|
||||
|
||||
def list
|
||||
@current_tab = 'list'
|
||||
@cfg = FoodsoftConfig
|
||||
@dfl = FoodsoftConfig.config
|
||||
@keys = FoodsoftConfig.keys.select {|k| FoodsoftConfig.allowed_key?(k)}.sort
|
||||
end
|
||||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
# TODO support nested configuration keys
|
||||
params[:config].each do |key, val|
|
||||
FoodsoftConfig[key] = val
|
||||
end
|
||||
end
|
||||
flash[:notice] = I18n.t('admin.configs.update.notice')
|
||||
redirect_to action: 'show'
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Set configuration tab names as `@tabs`
|
||||
def get_tabs
|
||||
@tabs = %w(foodcoop payment tasks messages layout language others)
|
||||
# allow engines to modify this list
|
||||
engines = Rails::Engine.subclasses.map(&:instance).select { |e| e.respond_to?(:configuration) }
|
||||
engines.each { |e| e.configuration(@tabs, self) }
|
||||
@tabs.uniq!
|
||||
end
|
||||
|
||||
end
|
117
app/helpers/admin/configs_helper.rb
Normal file
117
app/helpers/admin/configs_helper.rb
Normal file
|
@ -0,0 +1,117 @@
|
|||
module Admin::ConfigsHelper
|
||||
# Returns form input for configuration key.
|
||||
# For configuration keys that contain a {Hash}, {ActiveView::Helpers::FormBuilder#fields_for fields_for} can be used.
|
||||
# @param form [ActionView::Helpers::FormBuilder] Form object.
|
||||
# @param key [Symbol, String] Configuration key.
|
||||
# @param options [Hash] Options passed to the form builder.
|
||||
# @option options [Boolean] :required Wether field is shown as required (default not).
|
||||
# @return [String] Form input for configuration key.
|
||||
def config_input(form, key, options = {}, &block)
|
||||
options[:label] = config_input_label(form, key)
|
||||
options[:required] ||= false
|
||||
options[:input_html] ||= {}
|
||||
config_input_field_options form, key, options[:input_html]
|
||||
config_input_tooltip_options form, key, options[:input_html]
|
||||
if options[:as] == :boolean
|
||||
options[:input_html][:checked] = 'checked' if options[:input_html].delete(:value)
|
||||
options[:checked_value] = true
|
||||
options[:unchecked_value] = false
|
||||
elsif options[:collection] or options[:as] == :select
|
||||
options[:selected] = options[:input_html].delete(:value)
|
||||
return form.input key, options, &block
|
||||
end
|
||||
form.input key, options, &block
|
||||
end
|
||||
|
||||
# @return [String] Label name in form for configuration key.
|
||||
# @param form [ActionView::Helpers::FormBuilder] Form object.
|
||||
# @param key [Symbol, String] Configuration key.
|
||||
# @see #config_input
|
||||
def config_input_label(form, key)
|
||||
cfg_path = form.lookup_model_names[1..-1] + [key]
|
||||
I18n.t("config.keys.#{cfg_path.map(&:to_s).join('.')}")
|
||||
end
|
||||
|
||||
# @return [String] Form input field for configuration key.
|
||||
# @see config_input
|
||||
# @todo find out how to pass +checked_value+ and +unchecked_value+ to +input_field+
|
||||
def config_input_field(form, key, options = {})
|
||||
config_input_field_options form, key, options
|
||||
config_input_tooltip_options form, key, options
|
||||
if options[:as] == :boolean
|
||||
options[:checked] = 'checked' if options.delete(:value)
|
||||
form.hidden_field(key, value: false, as: :hidden) + form.check_box(key, options, true, false)
|
||||
else
|
||||
form.input_field key, options
|
||||
end
|
||||
end
|
||||
|
||||
# @return [String] Form heading with checkbox with block passed in expandable +fieldset+.
|
||||
# @param form [ActionView::Helpers::FormBuilder] Form object.
|
||||
# @param key [Symbol, String] Configuration key of a boolean (e.g. +use_messages+).
|
||||
# @option options [String] :label Label to show
|
||||
def config_use_heading(form, key, options = {})
|
||||
head = content_tag :label do
|
||||
lbl = options[:label] || config_input_label(form, key)
|
||||
field = config_input_field(form, key, as: :boolean, boolean_style: :inline,
|
||||
data: {toggle: 'collapse', target: "##{key}-fields"})
|
||||
content_tag :h4 do
|
||||
# put in span to keep space for tooltip at right
|
||||
content_tag :span, (lbl + field).html_safe, config_input_tooltip_options(form, key, {})
|
||||
end
|
||||
end
|
||||
fields = content_tag(:fieldset, id: "#{key}-fields", class: "collapse#{' in' if @cfg[key]}") do
|
||||
yield
|
||||
end
|
||||
head + fields
|
||||
end
|
||||
|
||||
# Returns configuration value suitable for rendering in HTML.
|
||||
# Makes keys different from +app_config.yml+ configuration bold,
|
||||
# protects sensitive values like keys and passwords, and makes
|
||||
# links from URLs.
|
||||
# @param key [String] Configuration key
|
||||
# @param value [String] Configuration value
|
||||
# @return [String] Configuration value suitable for rendering in HTML.
|
||||
def show_config_value(key, value)
|
||||
if key =~ /passw|secr|key/
|
||||
'(protected)'
|
||||
elsif value.is_a? Hash
|
||||
content_tag :ul do
|
||||
value.map do |k,v|
|
||||
content_tag :li, content_tag(:tt, "#{k}: ") + show_config_value(k, v).to_s
|
||||
end.join.html_safe
|
||||
end
|
||||
elsif value.is_a? Enumerable
|
||||
content_tag :ul, value.map {|v| content_tag :li, h(v)}.join.html_safe
|
||||
elsif key =~ /url|website|www|homepage/
|
||||
link_to(value, value).html_safe
|
||||
else
|
||||
value
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def config_input_tooltip_options(form, key, options)
|
||||
# tooltip with help info to the right
|
||||
cfg_path = form.lookup_model_names[1..-1] + [key]
|
||||
tooltip = I18n.t("config.hints.#{cfg_path.map(&:to_s).join('.')}", default: '')
|
||||
unless tooltip.blank?
|
||||
options[:data] ||= {}
|
||||
options[:data][:toggle] ||= 'tooltip'
|
||||
options[:data][:placement] ||= 'right'
|
||||
options[:title] ||= tooltip
|
||||
end
|
||||
options
|
||||
end
|
||||
|
||||
def config_input_field_options(form, key, options)
|
||||
cfg_path = form.lookup_model_names[1..-1] + [key]
|
||||
# set current value
|
||||
value = @cfg
|
||||
cfg_path.each {|n| value = value[n] unless value.nil? }
|
||||
options[:value] ||= value
|
||||
options
|
||||
end
|
||||
end
|
10
app/views/admin/configs/_tab_foodcoop.html.haml
Normal file
10
app/views/admin/configs/_tab_foodcoop.html.haml
Normal file
|
@ -0,0 +1,10 @@
|
|||
= config_input form, :name, required: true, input_html: {class: 'input-xlarge'}
|
||||
= form.fields_for :contact do |c|
|
||||
= config_input c, :street, input_html: {class: 'input-xlarge'}
|
||||
.fold-line
|
||||
= config_input c, :zip_code, input_html: {class: 'input-mini'}
|
||||
= config_input c, :city, input_html: {class: 'input-medium'}
|
||||
= config_input c, :country, as: :string, input_html: {class: 'input-xlarge'}
|
||||
= config_input c, :email, required: true, input_html: {class: 'input-xlarge'}
|
||||
= config_input c, :phone, input_html: {class: 'input-medium'}
|
||||
= config_input form, :homepage, required: true, as: :url, input_html: {class: 'input-xlarge'}
|
3
app/views/admin/configs/_tab_language.html.haml
Normal file
3
app/views/admin/configs/_tab_language.html.haml
Normal file
|
@ -0,0 +1,3 @@
|
|||
= config_input form, :default_locale,
|
||||
collection: I18n.available_locales.map {|l| [t("simple_form.options.settings.profile.language.#{l}"), l]}
|
||||
= config_input form, :ignore_browser_locale, as: :boolean
|
7
app/views/admin/configs/_tab_layout.html.haml
Normal file
7
app/views/admin/configs/_tab_layout.html.haml
Normal file
|
@ -0,0 +1,7 @@
|
|||
= config_input form, :page_footer, as: :text, input_html: {class: 'input-xxlarge', rows: 2, placeholder: "#{link_to(FoodsoftConfig[:name], FoodsoftConfig[:homepage])}"}
|
||||
|
||||
%h4= t '.pdf_title'
|
||||
.fold-line
|
||||
= config_input form, :pdf_font_size, as: :integer, input_html: {class: 'input-mini'}
|
||||
= config_input form, :pdf_page_size, input_html: {class: 'input-medium'}
|
||||
= config_input form, :pdf_add_page_breaks, as: :boolean
|
7
app/views/admin/configs/_tab_messages.html.haml
Normal file
7
app/views/admin/configs/_tab_messages.html.haml
Normal file
|
@ -0,0 +1,7 @@
|
|||
%fieldset
|
||||
%label
|
||||
%h4= t '.emails_title'
|
||||
= config_input form, :email_from, as: :string, input_html: {class: 'input-xlarge', placeholder: "#{@cfg[:name]} <#{@cfg[:contact][:email]}>"}
|
||||
= config_input form, :email_replyto, as: :string, input_html: {class: 'input-xlarge'}
|
||||
-# sender is better configured by server administrator, since it affects SPF records
|
||||
-#= config_input form, :email_sender, as: :string, input_html: {class: 'input-xlarge'}
|
5
app/views/admin/configs/_tab_others.html.haml
Normal file
5
app/views/admin/configs/_tab_others.html.haml
Normal file
|
@ -0,0 +1,5 @@
|
|||
- if defined? FoodsoftWiki # avoid requiring deface here (the single exception)
|
||||
= config_input form, :use_wiki, as: :boolean
|
||||
= config_input form, :use_nick, as: :boolean
|
||||
= config_input form, :tolerance_is_costly, as: :boolean
|
||||
= config_input form, :help_url, as: :url, input_html: {class: 'input-xlarge'}
|
12
app/views/admin/configs/_tab_payment.html.haml
Normal file
12
app/views/admin/configs/_tab_payment.html.haml
Normal file
|
@ -0,0 +1,12 @@
|
|||
= config_input form, :price_markup do
|
||||
.input-append
|
||||
= config_input_field form, :price_markup, as: :decimal, class: 'input-mini'
|
||||
%span.add-on %
|
||||
= config_input form, :tax_default do
|
||||
.input-append
|
||||
= config_input_field form, :tax_default, as: :decimal, class: 'input-mini'
|
||||
%span.add-on %
|
||||
= config_input form, :minimum_balance do
|
||||
.input-prepend
|
||||
%span.add-on= t 'number.currency.format.unit'
|
||||
= config_input_field form, :minimum_balance, as: :decimal, class: 'input-small'
|
3
app/views/admin/configs/_tab_tasks.html.haml
Normal file
3
app/views/admin/configs/_tab_tasks.html.haml
Normal file
|
@ -0,0 +1,3 @@
|
|||
-#= config_use_heading form, :use_tasks do
|
||||
= config_use_heading form, :use_apple_points do
|
||||
= config_input form, :stop_ordering_under, as: :numeric, input_html: {class: 'input-small'}
|
11
app/views/admin/configs/_tabs.html.haml
Normal file
11
app/views/admin/configs/_tabs.html.haml
Normal file
|
@ -0,0 +1,11 @@
|
|||
%ul.nav.nav-tabs.nav-tabs-with-heading
|
||||
%li.heading
|
||||
%h1= t '.title'
|
||||
|
||||
- for tab in @tabs
|
||||
- url = action_name == 'show' ? nil : admin_config_path(tab: tab)
|
||||
%li{class: ('active' if @current_tab==tab)}= link_to t("config.tabs.#{tab}"), "#{url}#tab-#{tab}", data: ({toggle: 'tab'} unless url)
|
||||
|
||||
-# make this a button to give some indicator that navigation away might lose changes
|
||||
%li.pull-right{class: ('active' if @current_tab=='list')}
|
||||
= link_to t('config.tabs.list'), list_admin_config_path, class: ('btn' unless @current_tab=='list')
|
16
app/views/admin/configs/list.html.haml
Normal file
16
app/views/admin/configs/list.html.haml
Normal file
|
@ -0,0 +1,16 @@
|
|||
- title t('.title'), false
|
||||
|
||||
= render 'tabs'
|
||||
|
||||
%table.table
|
||||
%thead
|
||||
%tr
|
||||
%th= t '.key'
|
||||
%th= t '.value'
|
||||
%tbody
|
||||
- @keys.each do |key|
|
||||
%tr
|
||||
%td
|
||||
%tt= key
|
||||
%td{style: if @cfg[key] != @dfl[key] then 'font-weight: bold' end}
|
||||
= show_config_value key, @cfg[key]
|
13
app/views/admin/configs/show.html.haml
Normal file
13
app/views/admin/configs/show.html.haml
Normal file
|
@ -0,0 +1,13 @@
|
|||
- title t('admin.configs.tabs.title'), false
|
||||
|
||||
= simple_form_for :config, method: :patch do |f|
|
||||
|
||||
= render 'tabs', url: nil
|
||||
|
||||
.tab-content
|
||||
- for tab in @tabs
|
||||
.tab-pane{class: ('active' if @current_tab==tab), id: "tab-#{tab}"}= render "tab_#{tab}", form: f
|
||||
|
||||
.form-actions
|
||||
= f.submit t('.submit'), class: 'btn btn-primary'
|
||||
|
|
@ -10,9 +10,9 @@
|
|||
%li= link_to t('.profile'), my_profile_path
|
||||
%li= link_to t('.ordergroup'), my_ordergroup_path
|
||||
%li= link_to t('.logout'), logout_path
|
||||
%li{class: ('disabled' if FoodsoftConfig.config[:homepage].blank?)}
|
||||
= link_to FoodsoftConfig.config[:name], FoodsoftConfig.config[:homepage]
|
||||
%li= link_to t('.help'), FoodsoftConfig.config[:help_url]
|
||||
%li{class: ('disabled' if FoodsoftConfig[:homepage].blank?)}
|
||||
= link_to FoodsoftConfig[:name], FoodsoftConfig[:homepage]
|
||||
%li= link_to t('.help'), FoodsoftConfig[:help_url]
|
||||
%li= link_to t('.feedback.title'), new_feedback_path, title: t('.feedback.desc')
|
||||
.clearfix
|
||||
|
||||
|
|
|
@ -225,6 +225,22 @@ en:
|
|||
title: Administration
|
||||
type: type
|
||||
username: username
|
||||
configs:
|
||||
list:
|
||||
title: Configuration list
|
||||
key: Key
|
||||
value: Value
|
||||
show:
|
||||
title: Configuration
|
||||
submit: Save
|
||||
tab_layout:
|
||||
pdf_title: PDF documents
|
||||
tabs:
|
||||
title: Configuration
|
||||
tab_messages:
|
||||
emails_title: Sending email
|
||||
update:
|
||||
notice: Configuration saved.
|
||||
confirm: Do you really want to delete %{name}?
|
||||
ordergroups:
|
||||
destroy:
|
||||
|
@ -419,6 +435,75 @@ en:
|
|||
file_label: Please choose a compatible file
|
||||
submit: Upload file
|
||||
title: '%{supplier} / upload articles'
|
||||
config:
|
||||
tabs:
|
||||
foodcoop: Foodcoop
|
||||
payment: Finances
|
||||
language: Language
|
||||
messages: Messages
|
||||
tasks: Tasks
|
||||
layout: Layout
|
||||
others: Other
|
||||
list: List
|
||||
hints:
|
||||
name: The name of your foodcoop.
|
||||
contact:
|
||||
email: General contact email address, shown on website as well as some forms.
|
||||
street: Address, typically this will be your delivery and pick-up location.
|
||||
homepage: Website of your foodcoop.
|
||||
help_url: Documentation website.
|
||||
applepear_url: Website where the apple and pear system for tasks is explained.
|
||||
ignore_browser_locale: "Ignore the language of user's computer when the user has not chosen a language yet."
|
||||
price_markup: Percentage that is added to the gross price for foodcoop members.
|
||||
tax_default: Default VAT percentage for new articles.
|
||||
stop_ordering_under: Members can only order when they have at least this many apple points.
|
||||
minimum_balance: Members can only order when their account balance is above or equal to this amount.
|
||||
use_apple_points: When the apple point system is enabled, members are required to do some tasks to be able to keep ordering.
|
||||
use_nick: Show and use nicknames instead of real names. When enabling this, please check that each user has a nickname.
|
||||
use_messages: Allow members to communicate with each other within Foodsoft.
|
||||
use_wiki: Enable editable wiki pages.
|
||||
email_sender: "Emails will appear to be sent from this email address. To avoid emails sent being classified as spam, the webserver may need to be registered in the SPF record of the email address's domain."
|
||||
email_from: "Emails will appear to be from this email address. Leave empty to use the foodcoop's contact address."
|
||||
email_replyto: Set this when you want to receive replies from emails sent by Foodsoft on a different address than the above.
|
||||
mailing_list: Mailing-list email address to use instead of the messaging system for mail to all members.
|
||||
mailing_list_subscribe: Email address where members can send an email to for subscribing.
|
||||
page_footer: 'Shown on each page at the bottom. Enter "blank" to disable the footer completely.'
|
||||
pdf_font_size: Base font size for PDF documents (12 is standard).
|
||||
pdf_page_size: 'Page size for PDF documents, typically "A4" or "letter".'
|
||||
pdf_add_page_breaks: Add page breaks when starting a new section.
|
||||
tolerance_is_costly: "Order as much of the member tolerance as possible (compared to only as much needed to fill the last box). Enabling this also includes the tolerance in the total price of the open member order."
|
||||
keys:
|
||||
name: Name
|
||||
contact:
|
||||
street: Street
|
||||
zip_code: Postcode
|
||||
city: City
|
||||
country: Country
|
||||
email: Email
|
||||
phone: Phone
|
||||
homepage: Homepage
|
||||
help_url: Documentation URL
|
||||
applepear_url: Apple system URL
|
||||
default_locale: Default language
|
||||
ignore_browser_locale: Ignore browser language
|
||||
price_markup: Foodcoop margin
|
||||
tax_default: Default VAT
|
||||
tolerance_is_costly: Tolerance is costly
|
||||
stop_ordering_under: Minimum apple points
|
||||
use_apple_points: Apple points
|
||||
minimum_balance: Minimum account balance
|
||||
use_nick: Use nicknames
|
||||
use_messages: Enable messages
|
||||
use_wiki: Enable wiki
|
||||
email_sender: Sender address
|
||||
email_from: From address
|
||||
email_replyto: Reply-to address
|
||||
mailing_list: Mailing-list
|
||||
mailing_list_subscribe: Mailing-list subscribe
|
||||
page_footer: Page footer
|
||||
pdf_font_size: Font size
|
||||
pdf_page_size: Page size
|
||||
pdf_add_page_breaks: Page breaks
|
||||
deliveries:
|
||||
add_stock_change:
|
||||
how_many_units: 'How many units (%{unit}) to deliver? Stock article name: %{name}.'
|
||||
|
@ -1043,6 +1128,7 @@ en:
|
|||
no_ordergroup: no ordergroup
|
||||
navigation:
|
||||
admin:
|
||||
config: Configuration
|
||||
home: Overview
|
||||
ordergroups: Ordergroups
|
||||
title: Administration
|
||||
|
|
|
@ -213,6 +213,22 @@ nl:
|
|||
title: Administratie
|
||||
type: Type
|
||||
username: Gebruikersnaam
|
||||
configs:
|
||||
list:
|
||||
title: Configuratielijst
|
||||
key: Sleutel
|
||||
value: Inhoud
|
||||
show:
|
||||
title: Configuratie
|
||||
submit: Opslaan
|
||||
tab_layout:
|
||||
pdf_title: PDF documenten
|
||||
tabs:
|
||||
title: Configuratie
|
||||
tab_messages:
|
||||
emails_title: Emailinstellingen
|
||||
update:
|
||||
notice: Configuratie opgeslagen.
|
||||
confirm: Wil je %{name} daadwerkelijk wissen?
|
||||
ordergroups:
|
||||
destroy:
|
||||
|
@ -402,6 +418,75 @@ nl:
|
|||
file_label: Graag een compatibel bestand uitkiezen
|
||||
submit: Bestand uploaden
|
||||
title: Artikelen uploaden voor %{supplier}
|
||||
config:
|
||||
tabs:
|
||||
foodcoop: Foodcoop
|
||||
payment: Financiën
|
||||
language: Taal
|
||||
messages: Berichten
|
||||
tasks: Taken
|
||||
layout: Layout
|
||||
others: Overig
|
||||
list: Lijst
|
||||
hints:
|
||||
name: De naam van de foodcoop.
|
||||
contact:
|
||||
email: Algemeen contactadres, zowel voor op de website als in formulieren.
|
||||
street: Adres, meestal is dit het aflever- en ophaaladres.
|
||||
homepage: Website van de foodcoop.
|
||||
help_url: Documentatie website.
|
||||
applepear_url: Website waar het appelpunten systeem wordt uitgelegd.
|
||||
ignore_browser_locale: Negeer de taal van de computer wanneer iemand nog geen taal gekozen heeft.
|
||||
price_markup: Percentage dat bovenop het brutobedrag wordt gedaan voor foodcoop leden.
|
||||
tax_default: Standaard BTW percentage voor nieuwe artikelen.
|
||||
stop_ordering_under: Leden kunnen slechts bestellen als ze dit aantal appelpunten hebben of meer.
|
||||
minimum_balance: Leden kunnen slechts bestellen wanneer hun tegoed groter of gelijk is aan dit bedrag.
|
||||
use_apple_points: Wanneer het appelpunten systeem is geactiveerd, kunnen leden slechts bestellen wanneer ze meewerken aan taken.
|
||||
use_nick: Toon bijnamen in plaats van volledige naam. Controleer dat iedereen een bijnaam heeft wanneer je dit aanzet.
|
||||
use_messages: Laat leden met elkaar communiceren door middel van berichten binnen Foodsoft.
|
||||
use_wiki: "Gebruik wiki pagina's."
|
||||
email_sender: "Emails worden verzonden vanaf dit emailadres. Om te voorkomen dat emails als spam worden tegengehouden, is het te adviseren het adres van de webserver op te nemen in het SPF record van het email domein."
|
||||
email_from: "Emails zullen lijken verzonden te zijn vanaf dit email adres. Laat het veld leeg om het contactadres van de foodcoop te gebruiken."
|
||||
email_replyto: Vul dit in als je antwoord op mails van Foodsoft wilt ontvangen op een ander adres dan het bovenstaande.
|
||||
mailing_list: Mailing-lijst adres om te gebruiken in plaats van het berichtensysteem voor emails naar alle leden.
|
||||
mailing_list_subscribe: Emailadres waar leden zich kunnen aanmelden voor de mailing-lijst.
|
||||
page_footer: 'Wordt op iedere pagina getoond. Vul "blank" in om de voettekst helemaal weg te halen.'
|
||||
pdf_font_size: Basis tekstgrootte voor PDF bestanden (standaard 12).
|
||||
pdf_page_size: 'Paginaformaat voor PDF bestanden, meestal "A4" of "letter".'
|
||||
pdf_add_page_breaks: Secties op een nieuwe pagina beginnen.
|
||||
tolerance_is_costly: "Bestel zoveel artikelen als mogelijk in de tolerantie (in plaats van net genoeg om de laatste doos te vullen). Dit zorgt er ook voor dat de tolerantie in de prijs van open ledenbestellingen wordt meegenomen."
|
||||
keys:
|
||||
name: Naam
|
||||
contact:
|
||||
street: Straat
|
||||
zip_code: Postcode
|
||||
city: Stad
|
||||
country: Land
|
||||
email: Email
|
||||
phone: Telefoon
|
||||
homepage: Homepage
|
||||
help_url: Documentatie URL
|
||||
applepear_url: Appelsysteem uitleg URL
|
||||
default_locale: Standaardtaal
|
||||
ignore_browser_locale: Browsertaal negeren
|
||||
price_markup: Foodcoop marge
|
||||
tax_default: Standaard BTW
|
||||
tolerance_is_costly: Tolerantie is duur
|
||||
stop_ordering_under: Minimum appelpunten
|
||||
use_apple_points: Appelpunten
|
||||
minimum_balance: Minimum tegoed
|
||||
use_nick: Bijnamen gebruiken
|
||||
use_messages: Berichten gebruiken
|
||||
use_wiki: Wiki gebruiken
|
||||
email_sender: Sender adres
|
||||
email_from: From adres
|
||||
email_replyto: Reply-to adres
|
||||
mailing_list: Mailing-lijst
|
||||
mailing_list_subscribe: Mailing-lijst aanmelden
|
||||
page_footer: Voettkest
|
||||
pdf_font_size: Tekstgrootte
|
||||
pdf_page_size: Paginaformaat
|
||||
pdf_add_page_breaks: "Nieuwe pagina's"
|
||||
deliveries:
|
||||
add_stock_change:
|
||||
how_many_units: 'Hoeveel eenheden (%{unit}) leveren? Voorraadartikel: %{name}.'
|
||||
|
@ -1023,6 +1108,7 @@ nl:
|
|||
no_ordergroup: geen huishouden
|
||||
navigation:
|
||||
admin:
|
||||
config: Instellingen
|
||||
home: Overzicht
|
||||
ordergroups: Huishoudens
|
||||
title: Administratie
|
||||
|
|
|
@ -45,6 +45,7 @@ SimpleNavigation::Configuration.run do |navigation|
|
|||
subnav.item :users, I18n.t('navigation.admin.users'), admin_users_path
|
||||
subnav.item :ordergroups, I18n.t('navigation.admin.ordergroups'), admin_ordergroups_path
|
||||
subnav.item :workgroups, I18n.t('navigation.admin.workgroups'), admin_workgroups_path
|
||||
subnav.item :config, I18n.t('navigation.admin.config'), admin_config_path
|
||||
end
|
||||
|
||||
engines.each { |e| e.navigation(primary, self) }
|
||||
|
|
|
@ -181,6 +181,10 @@ Foodsoft::Application.routes.draw do
|
|||
resources :ordergroups do
|
||||
get :memberships, :on => :member
|
||||
end
|
||||
|
||||
resource :config, :only => [:show, :update] do
|
||||
get :list
|
||||
end
|
||||
end
|
||||
|
||||
############## Feedback
|
||||
|
|
|
@ -1,9 +1,37 @@
|
|||
# Foodcoop-specific configuration.
|
||||
#
|
||||
# This is loaded from +config/app_config.yml+, which contains a root
|
||||
# key for each environment (plus an optional +defaults+ key). When using
|
||||
# the multicoops feature (+multicoops+ is set to +true+ for the environment),
|
||||
# each foodcoop has its own key.
|
||||
#
|
||||
# In addition to the configuration file, values can be overridden in the database
|
||||
# using {RailsSettings::CachedSettings} as +foodcoop.<foodcoop_scope>.**+.
|
||||
#
|
||||
class FoodsoftConfig
|
||||
mattr_accessor :scope, :config
|
||||
|
||||
# @!attribute scope
|
||||
# Returns the current foodcoop scope for the multicoops feature, otherwise
|
||||
# the value of the foodcoop configuration key +default_scope+ is used.
|
||||
# @return [String] The current foodcoop scope.
|
||||
mattr_accessor :scope
|
||||
# @!attribute config
|
||||
# Returns a {ActiveSupport::HashWithIndifferentAccess Hash} with the current
|
||||
# scope's configuration from the configuration file. Note that this does not
|
||||
# include values that were changed in the database.
|
||||
# @return [ActiveSupport::HashWithIndifferentAccess] Current configuration from configuration file.
|
||||
mattr_accessor :config
|
||||
|
||||
# Configuration file location.
|
||||
# Taken from environment variable +FOODSOFT_APP_CONFIG+,
|
||||
# or else +config/app_config.yml+.
|
||||
APP_CONFIG_FILE = ENV['FOODSOFT_APP_CONFIG'] || 'config/app_config.yml'
|
||||
# Rails.logger isn't ready yet - and we don't want to litter rspec invocation with this msg
|
||||
puts "-> Loading app configuration from #{APP_CONFIG_FILE}" unless defined? RSpec
|
||||
APP_CONFIG = YAML.load(File.read(File.expand_path(APP_CONFIG_FILE, Rails.root)))
|
||||
# Loaded configuration
|
||||
APP_CONFIG = ActiveSupport::HashWithIndifferentAccess.new(
|
||||
YAML.load(File.read(File.expand_path(APP_CONFIG_FILE, Rails.root)))
|
||||
)
|
||||
|
||||
class << self
|
||||
|
||||
|
@ -16,17 +44,71 @@ class FoodsoftConfig
|
|||
set_missing
|
||||
end
|
||||
|
||||
# Set config and database connection for specific foodcoop
|
||||
# Only needed in multi coop mode
|
||||
# Set config and database connection for specific foodcoop.
|
||||
#
|
||||
# Only needed in multi coop mode.
|
||||
# @param foodcoop [String, Symbol] Foodcoop to select.
|
||||
def select_foodcoop(foodcoop)
|
||||
set_config foodcoop
|
||||
setup_database
|
||||
end
|
||||
|
||||
# Provides a nice accessor for config values
|
||||
# FoodsoftConfig[:name] # => 'FC Test'
|
||||
# Return configuration value for the currently selected foodcoop.
|
||||
#
|
||||
# First tries to read configuration from the database (cached),
|
||||
# then from the configuration files.
|
||||
#
|
||||
# FoodsoftConfig[:name] # => 'FC Test'
|
||||
#
|
||||
# @param key [String, Symbol]
|
||||
# @return [Object] Value of the key.
|
||||
def [](key)
|
||||
RailsSettings::CachedSettings["foodcoop.#{self.scope}.#{key}"] || config[key]
|
||||
if allowed_key?(key)
|
||||
value = RailsSettings::CachedSettings["foodcoop.#{self.scope}.#{key}"]
|
||||
value = config[key] if value.nil?
|
||||
value
|
||||
else
|
||||
config[key]
|
||||
end
|
||||
end
|
||||
|
||||
# Store configuration in the database.
|
||||
#
|
||||
# If value is equal to what's defined in the configuration file, remove key from the database.
|
||||
# @param key [String, Symbol] Key
|
||||
# @param value [Object] Value
|
||||
# @return [Boolean] Whether storing succeeded (fails when key is not allowed to be set in database).
|
||||
def []=(key, value)
|
||||
return false unless allowed_key?(key)
|
||||
# try to figure out type ...
|
||||
value = case value
|
||||
when 'true' then true
|
||||
when 'false' then false
|
||||
when /^[-+0-9]+$/ then value.to_i
|
||||
when /^[-+0-9.]+([eE][-+0-9]+)?$/ then value.to_f
|
||||
when '' then nil
|
||||
else value
|
||||
end
|
||||
# then update database
|
||||
if config[key] == value or (config[key].nil? and value == false)
|
||||
# delete (ok if it was already deleted)
|
||||
begin
|
||||
RailsSettings::CachedSettings.destroy "foodcoop.#{self.scope}.#{key}"
|
||||
rescue RailsSettings::Settings::SettingNotFound
|
||||
end
|
||||
else
|
||||
# or store
|
||||
RailsSettings::CachedSettings["foodcoop.#{self.scope}.#{key}"] = value
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
# @return [Array<String>] Configuration keys that are set (either in +app_config.yml+ or database).
|
||||
def keys
|
||||
keys = RailsSettings::CachedSettings.get_all("foodcoop.#{self.scope}.").try(:keys) || []
|
||||
keys.map! {|k| k.gsub /^foodcoop\.#{self.scope}\./, ''}
|
||||
keys += config.keys
|
||||
keys.map(&:to_s).uniq
|
||||
end
|
||||
|
||||
# Loop through each foodcoop and executes the given block after setup config and database
|
||||
|
@ -41,11 +123,18 @@ class FoodsoftConfig
|
|||
end
|
||||
end
|
||||
|
||||
# @return [Boolean] Whether this key may be set in the database
|
||||
def allowed_key?(key)
|
||||
# fast check for keys without nesting
|
||||
return !self.config[:protected].keys.include?(key)
|
||||
# @todo allow to check nested keys as well
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_config(foodcoop)
|
||||
raise "No config for this environment (#{foodcoop}) available!" if APP_CONFIG[foodcoop].nil?
|
||||
self.config = APP_CONFIG[foodcoop].symbolize_keys
|
||||
self.config = APP_CONFIG[foodcoop]
|
||||
self.scope = foodcoop
|
||||
set_missing
|
||||
end
|
||||
|
@ -62,7 +151,18 @@ class FoodsoftConfig
|
|||
config.replace({
|
||||
use_nick: true,
|
||||
use_apple_points: true,
|
||||
foodsoft_url: 'https://github.com/foodcoops/foodsoft'
|
||||
# English is the default language, and this makes it show up as default.
|
||||
default_locale: 'en',
|
||||
foodsoft_url: 'https://github.com/foodcoops/foodsoft',
|
||||
# The following keys cannot be set by foodcoops themselves.
|
||||
protected: {
|
||||
multi_coop_install: nil,
|
||||
default_scope: nil,
|
||||
notification: nil,
|
||||
shared_lists: nil,
|
||||
protected: nil,
|
||||
database: nil
|
||||
}
|
||||
}.merge(config))
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
/ insert_bottom ':root'
|
||||
= config_use_heading form, :use_messages, label: 'Messages' do
|
||||
= config_input form, :mailing_list, as: :string, input_html: {class: 'input-xlarge'}
|
||||
= config_input form, :mailing_list_subscribe, as: :string, input_html: {class: 'input-xlarge'}
|
Loading…
Reference in a new issue