symphonia 2.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +16 -0
- data/Rakefile +44 -0
- data/app/assets/images/bg-checker.png +0 -0
- data/app/assets/images/bullet.gif +0 -0
- data/app/assets/images/close.png +0 -0
- data/app/assets/images/loading.gif +0 -0
- data/app/assets/images/next.png +0 -0
- data/app/assets/images/prev.png +0 -0
- data/app/assets/javascripts/ckeditor/plugins/autogrow/plugin.js +232 -0
- data/app/assets/javascripts/ckeditor/plugins/autogrow/samples/autogrow.html +102 -0
- data/app/assets/javascripts/ckeditor/plugins/image_chooser/icons/addimage.png +0 -0
- data/app/assets/javascripts/ckeditor/plugins/image_chooser/plugin.js +15 -0
- data/app/assets/javascripts/symphonia/Sortable.js +1249 -0
- data/app/assets/javascripts/symphonia/_core.js +45 -0
- data/app/assets/javascripts/symphonia/application.js.erb +147 -0
- data/app/assets/javascripts/symphonia/filters.js +44 -0
- data/app/assets/javascripts/symphonia/symphonia_bootstrap_dialog.js +136 -0
- data/app/assets/javascripts/symphonia/symphonia_ckeditor.js +55 -0
- data/app/assets/stylesheets/symphonia/application.css +4 -0
- data/app/assets/stylesheets/symphonia/basic.scss +218 -0
- data/app/assets/stylesheets/symphonia/filters.scss +19 -0
- data/app/assets/stylesheets/symphonia/symphonia_bootstrap.scss +56 -0
- data/app/channels/application_cable/channel.rb +5 -0
- data/app/controllers/symphonia/accounts_controller.rb +169 -0
- data/app/controllers/symphonia/admin_controller.rb +22 -0
- data/app/controllers/symphonia/api_controller.rb +64 -0
- data/app/controllers/symphonia/application_controller.rb +8 -0
- data/app/controllers/symphonia/attachments_controller.rb +37 -0
- data/app/controllers/symphonia/filters_controller.rb +23 -0
- data/app/controllers/symphonia/images_controller.rb +16 -0
- data/app/controllers/symphonia/login_controller.rb +80 -0
- data/app/controllers/symphonia/roles_controller.rb +100 -0
- data/app/controllers/symphonia/user_sessions_controller.rb +16 -0
- data/app/controllers/symphonia/users_controller.rb +168 -0
- data/app/helpers/symphonia/application_helper.rb +422 -0
- data/app/helpers/symphonia/bootstrap_modal_helper.rb +59 -0
- data/app/helpers/symphonia/form_helper.rb +50 -0
- data/app/helpers/symphonia/renderer_helper.rb +85 -0
- data/app/mailers/symphonia/application_mailer.rb +6 -0
- data/app/mailers/symphonia/notifier.rb +42 -0
- data/app/models/symphonia/admin_module.rb +18 -0
- data/app/models/symphonia/application_record.rb +14 -0
- data/app/models/symphonia/attachment.rb +16 -0
- data/app/models/symphonia/common_file.rb +9 -0
- data/app/models/symphonia/email_preference.rb +5 -0
- data/app/models/symphonia/image.rb +46 -0
- data/app/models/symphonia/preference.rb +12 -0
- data/app/models/symphonia/role.rb +55 -0
- data/app/models/symphonia/swagger/error_model.rb +19 -0
- data/app/models/symphonia/swagger/responses.rb +27 -0
- data/app/models/symphonia/user.rb +141 -0
- data/app/models/symphonia/user_session.rb +19 -0
- data/app/views/common/403.html.erb +5 -0
- data/app/views/common/404.html.erb +2 -0
- data/app/views/layouts/symphonia/_modal.html.erb +19 -0
- data/app/views/layouts/symphonia/_query.html.erb +51 -0
- data/app/views/layouts/symphonia/application.html.erb +45 -0
- data/app/views/layouts/symphonia/application.pdf.erb +15 -0
- data/app/views/layouts/symphonia/mailer.html.erb +13 -0
- data/app/views/symphonia/accounts/_detail.html.erb +65 -0
- data/app/views/symphonia/accounts/_form.html.erb +14 -0
- data/app/views/symphonia/accounts/edit.html.erb +9 -0
- data/app/views/symphonia/accounts/edit.js.erb +5 -0
- data/app/views/symphonia/accounts/lost_password.html.erb +6 -0
- data/app/views/symphonia/accounts/lost_password.js.erb +3 -0
- data/app/views/symphonia/accounts/new_activation.html.erb +11 -0
- data/app/views/symphonia/accounts/new_activation.js.erb +6 -0
- data/app/views/symphonia/accounts/register.html.erb +20 -0
- data/app/views/symphonia/accounts/reset_password.html.erb +18 -0
- data/app/views/symphonia/accounts/update.js.erb +1 -0
- data/app/views/symphonia/admin/index.html.erb +15 -0
- data/app/views/symphonia/attachments/destroy.js.erb +1 -0
- data/app/views/symphonia/common/_editable_images_grid.html.erb +12 -0
- data/app/views/symphonia/common/_filters.html.erb +23 -0
- data/app/views/symphonia/common/_locale_chooser.html.erb +16 -0
- data/app/views/symphonia/common/_share_links.html.erb +5 -0
- data/app/views/symphonia/filters/options.html.erb +36 -0
- data/app/views/symphonia/filters/options.js.erb +9 -0
- data/app/views/symphonia/filters/table.html.erb +21 -0
- data/app/views/symphonia/login/_form.html.erb +19 -0
- data/app/views/symphonia/login/new.html.erb +11 -0
- data/app/views/symphonia/login_sessions/new.html.erb +1 -0
- data/app/views/symphonia/notifier/activation_user.html.erb +7 -0
- data/app/views/symphonia/notifier/activation_user.text.erb +3 -0
- data/app/views/symphonia/notifier/reset_password_user.html.erb +7 -0
- data/app/views/symphonia/notifier/reset_password_user.text.erb +3 -0
- data/app/views/symphonia/notifier/test_mail.html.erb +2 -0
- data/app/views/symphonia/notifier/test_mail.text.erb +3 -0
- data/app/views/symphonia/notifier/user_change_to_active.html.erb +3 -0
- data/app/views/symphonia/notifier/user_change_to_active.text.erb +1 -0
- data/app/views/symphonia/notifier/user_registered.html.erb +13 -0
- data/app/views/symphonia/notifier/user_registered.text.erb +8 -0
- data/app/views/symphonia/roles/_form.html.erb +30 -0
- data/app/views/symphonia/roles/edit.html.erb +5 -0
- data/app/views/symphonia/roles/index.html.erb +6 -0
- data/app/views/symphonia/roles/new.html.erb +4 -0
- data/app/views/symphonia/roles/show.html.erb +5 -0
- data/app/views/symphonia/users/_form.html.erb +13 -0
- data/app/views/symphonia/users/edit.html.erb +26 -0
- data/app/views/symphonia/users/edit.js.erb +3 -0
- data/app/views/symphonia/users/edit_current.html.erb +7 -0
- data/app/views/symphonia/users/index.html.erb +5 -0
- data/app/views/symphonia/users/new.html.erb +8 -0
- data/app/views/symphonia/users/show.html.erb +63 -0
- data/config/locales/cs.yml +233 -0
- data/config/locales/en.yml +47 -0
- data/config/routes.rb +52 -0
- data/db/migrate/20130714140500_create_users.rb +49 -0
- data/db/migrate/20130714140501_create_roles.rb +16 -0
- data/db/migrate/20130714140502_create_preferences.rb +26 -0
- data/db/migrate/20130828175114_create_attachments.rb +20 -0
- data/db/migrate/20141213204351_create_admin_modules.rb +20 -0
- data/db/seeds.rb +12 -0
- data/lib/generators/symphonia/entity_controller/entity_controller_generator.rb +48 -0
- data/lib/generators/symphonia/entity_controller/templates/controller.rb +100 -0
- data/lib/generators/symphonia/query/query_generator.rb +37 -0
- data/lib/generators/symphonia/setup/setup_generator.rb +52 -0
- data/lib/generators/symphonia/setup/templates/404.html +26 -0
- data/lib/generators/symphonia/setup/templates/500.html +37 -0
- data/lib/generators/symphonia/setup/templates/Gemfile +18 -0
- data/lib/generators/symphonia/setup/templates/base_layout.html.erb +46 -0
- data/lib/generators/symphonia/setup/templates/design.scss +4 -0
- data/lib/generators/symphonia/setup/templates/settings.rb +65 -0
- data/lib/generators/symphonia/setup/templates/spec_helper.rb +18 -0
- data/lib/symphonia/action_cable/connection.rb +31 -0
- data/lib/symphonia/admin_constraint.rb +9 -0
- data/lib/symphonia/attachable.rb +35 -0
- data/lib/symphonia/base_controller.rb +96 -0
- data/lib/symphonia/bootstrap_link_render.rb +69 -0
- data/lib/symphonia/controller_extensions.rb +200 -0
- data/lib/symphonia/engine.rb +137 -0
- data/lib/symphonia/form_builder.rb +137 -0
- data/lib/symphonia/menu_manager.rb +23 -0
- data/lib/symphonia/model_attributes/attribute.rb +137 -0
- data/lib/symphonia/model_attributes.rb +102 -0
- data/lib/symphonia/model_filters/base.rb +82 -0
- data/lib/symphonia/model_filters/boolean_filter.rb +26 -0
- data/lib/symphonia/model_filters/date_filter.rb +81 -0
- data/lib/symphonia/model_filters/integer_filter.rb +18 -0
- data/lib/symphonia/model_filters/select_filter.rb +48 -0
- data/lib/symphonia/model_filters/string_filter.rb +18 -0
- data/lib/symphonia/model_filters.rb +10 -0
- data/lib/symphonia/object.rb +31 -0
- data/lib/symphonia/permissions.rb +93 -0
- data/lib/symphonia/query.rb +275 -0
- data/lib/symphonia/query_columns/attribute_column.rb +43 -0
- data/lib/symphonia/query_columns/generic_column.rb +165 -0
- data/lib/symphonia/query_columns.rb +8 -0
- data/lib/symphonia/spec_helper.rb +4 -0
- data/lib/symphonia/user_management.rb +58 -0
- data/lib/symphonia/version.rb +4 -0
- data/lib/symphonia.rb +20 -0
- data/spec/controllers/account_controller_spec.rb +90 -0
- data/spec/controllers/admin_controller_spec.rb +35 -0
- data/spec/controllers/api_controller_spec.rb +9 -0
- data/spec/controllers/filters_controller_spec.rb +35 -0
- data/spec/controllers/images_controller_spec.rb +5 -0
- data/spec/controllers/login_controller_spec.rb +20 -0
- data/spec/controllers/roles_controller_spec.rb +12 -0
- data/spec/controllers/users_controller_spec.rb +47 -0
- data/spec/factories/factories.rb +52 -0
- data/spec/helpers/symphonia/application_helper_spec.rb +62 -0
- data/spec/mailers/previews/symphonia/notifier_preview.rb +27 -0
- data/spec/mailers/symphonia/notifier_spec.rb +76 -0
- data/spec/models/attachment_spec.rb +22 -0
- data/spec/models/query/attribute_spec.rb +8 -0
- data/spec/models/query/symphonia_query_spec.rb +70 -0
- data/spec/models/role_spec.rb +13 -0
- data/spec/models/user_spec.rb +10 -0
- data/spec/rails_helper.rb +13 -0
- data/spec/requests/accounts_spec.rb +118 -0
- data/spec/requests/attachments_controller_spec.rb +23 -0
- data/spec/requests/login_spec.rb +26 -0
- data/spec/requests/roles_spec.rb +10 -0
- data/spec/requests/users_spec.rb +50 -0
- data/spec/spec_helper.rb +101 -0
- data/spec/support/common_file.txt +2 -0
- data/spec/support/query.rb +36 -0
- data/spec/support/shared.rb +62 -0
- data/spec/support/shared_controllers.rb +31 -0
- data/spec/support/stub_users.rb +32 -0
- data/spec/support/symphonia.jpg +0 -0
- data/spec/support/wait_for_ajax.rb +15 -0
- data/spec/version_spec.rb +5 -0
- data/spec/views/filters/options.html.erb_spec.rb +14 -0
- metadata +697 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
module Symphonia
|
|
2
|
+
module ControllerExtensions
|
|
3
|
+
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
class Unauthorized < Exception; end
|
|
9
|
+
|
|
10
|
+
before_action :current_user, :menu_item
|
|
11
|
+
before_action :set_default_locale
|
|
12
|
+
|
|
13
|
+
# force_ssl if: -> {Rails.env.production? && User.current.ssl?}
|
|
14
|
+
|
|
15
|
+
add_flash_types :warning
|
|
16
|
+
add_flash_types :error
|
|
17
|
+
|
|
18
|
+
rescue_from ::ActiveRecord::RecordNotFound do
|
|
19
|
+
render_404
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
rescue_from Unauthorized do
|
|
23
|
+
render_403
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
helper_method :current_user
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def back_url
|
|
31
|
+
url = params[:back_url]
|
|
32
|
+
if url.nil? && (referer = request.env['HTTP_REFERER'])
|
|
33
|
+
url = CGI.unescape(referer.to_s)
|
|
34
|
+
end
|
|
35
|
+
url
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# def redirect_back_or_default(default, options={})
|
|
39
|
+
# back_url = params[:back_url].to_s
|
|
40
|
+
# if back_url.present?
|
|
41
|
+
# begin
|
|
42
|
+
# uri = URI.parse(back_url)
|
|
43
|
+
# # do not redirect user to another host or to the login or register page
|
|
44
|
+
# if (uri.relative? || (uri.host == request.host)) && !uri.path.match(%r{/(login|account/register)})
|
|
45
|
+
# redirect_to(back_url)
|
|
46
|
+
# return
|
|
47
|
+
# end
|
|
48
|
+
# rescue URI::InvalidURIError
|
|
49
|
+
# logger.warn("Could not redirect to invalid URL #{back_url}")
|
|
50
|
+
# # redirect to default
|
|
51
|
+
# end
|
|
52
|
+
# elsif options[:referer]
|
|
53
|
+
# redirect_to_referer_or default
|
|
54
|
+
# return
|
|
55
|
+
# end
|
|
56
|
+
# redirect_to default, options
|
|
57
|
+
# false
|
|
58
|
+
# end
|
|
59
|
+
|
|
60
|
+
# Redirects to the request referer if present, redirects to args or call block otherwise.
|
|
61
|
+
def redirect_to_referer_or(*args, &block)
|
|
62
|
+
redirect_to :back
|
|
63
|
+
rescue ::ActionController::RedirectBackError
|
|
64
|
+
if args.any?
|
|
65
|
+
redirect_to *args
|
|
66
|
+
elsif block_given?
|
|
67
|
+
block.call
|
|
68
|
+
else
|
|
69
|
+
raise "#redirect_to_referer_or takes arguments or a block"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# private
|
|
74
|
+
|
|
75
|
+
def set_locale
|
|
76
|
+
client_lang = params.fetch(:locale, nil).presence || session[:locale].presence || request.env['HTTP_ACCEPT_LANGUAGE'].to_s.split(',').collect { |l| l.scan(/^[a-z]{2}/) }.flatten
|
|
77
|
+
@client_lang = Array(client_lang).detect { |l| I18n.available_locales.include?(l.to_sym) }
|
|
78
|
+
|
|
79
|
+
I18n.locale = (@client_lang || I18n.default_locale)
|
|
80
|
+
session[:locale] = I18n.locale
|
|
81
|
+
|
|
82
|
+
logger.debug "* Locale set to '#{I18n.locale}'"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def set_default_locale
|
|
86
|
+
if (enforce_default = Symphonia.config.default_locale)
|
|
87
|
+
I18n.locale = enforce_default
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# protected
|
|
92
|
+
|
|
93
|
+
def login_require(format = nil)
|
|
94
|
+
if current_user.nil? || !current_user.logged_in?
|
|
95
|
+
respond_to do |format|
|
|
96
|
+
format.html do
|
|
97
|
+
store_location
|
|
98
|
+
redirect_to symphonia.login_path, flash: { error: t(:text_login_require) }
|
|
99
|
+
end
|
|
100
|
+
format.json do
|
|
101
|
+
render json: { errors: 'You must be logged in to access this endpoint' }, status: 403
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
return false
|
|
105
|
+
end
|
|
106
|
+
true
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
alias_method :require_login, :login_require
|
|
110
|
+
alias_method :require_user, :login_require
|
|
111
|
+
|
|
112
|
+
def admin_require
|
|
113
|
+
return unless login_require
|
|
114
|
+
unless current_user.admin?
|
|
115
|
+
render_403
|
|
116
|
+
return false
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
alias_method :require_admin, :admin_require
|
|
121
|
+
|
|
122
|
+
def render_403
|
|
123
|
+
respond_to do |format|
|
|
124
|
+
format.html { render template: 'common/403', message: :notice_not_authorized, status: 403 }
|
|
125
|
+
format.js { render plain: "alert('#{t :text_access_deny}')", message: :notice_not_authorized, status: 403 }
|
|
126
|
+
format.json { head 403, message: :notice_not_authorized }
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def render_404
|
|
131
|
+
respond_to do |format|
|
|
132
|
+
format.html { render template: 'common/404', message: :notice_page_not_found, status: 404 }
|
|
133
|
+
format.json { head 404, message: :not_found }
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Renders a 200 response for successful updates or deletions via the API
|
|
138
|
+
def render_api_ok
|
|
139
|
+
head :ok
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Renders a head API response
|
|
143
|
+
def render_api_head(status)
|
|
144
|
+
head status
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def menu_item(item = nil)
|
|
148
|
+
@menu_item = (item || controller_name)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def current_user_session
|
|
152
|
+
return @current_user_session if defined?(@current_user_session)
|
|
153
|
+
@current_user_session = UserSession.find
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def current_user
|
|
157
|
+
return (Symphonia::User.current ||= @current_user) if defined?(@current_user)
|
|
158
|
+
@current_user = current_user_session && current_user_session.user
|
|
159
|
+
Symphonia::User.current = @current_user || Symphonia::User::Anonymous.new
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def authorize
|
|
163
|
+
if Symphonia::User.current.authorize?(controller_name, action_name)
|
|
164
|
+
return true
|
|
165
|
+
else
|
|
166
|
+
if Symphonia::User.current.logged_in?
|
|
167
|
+
raise Unauthorized
|
|
168
|
+
else
|
|
169
|
+
respond_to do |format|
|
|
170
|
+
format.html do
|
|
171
|
+
return redirect_to(symphonia.login_path(back_url: request.path), error: t(:text_error_login_required))
|
|
172
|
+
end
|
|
173
|
+
format.any { return head 401 }
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
raise Unauthorized
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def handle_unverified_request
|
|
181
|
+
# raise an exception
|
|
182
|
+
fail ActionController::InvalidAuthenticityToken
|
|
183
|
+
# or destroy session, redirect
|
|
184
|
+
if current_user_session
|
|
185
|
+
current_user_session.destroy
|
|
186
|
+
end
|
|
187
|
+
redirect_to main_app.root_url
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def store_location
|
|
191
|
+
session[:return_to] = request.url
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def redirect_back_or_default(default, options = {})
|
|
195
|
+
options ||= {}
|
|
196
|
+
redirect_to(params[:back_url] || default, options)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
end
|
|
200
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
require 'symphonia/object'
|
|
2
|
+
require 'symphonia/menu_manager'
|
|
3
|
+
require 'symphonia/permissions'
|
|
4
|
+
require 'symphonia/user_management'
|
|
5
|
+
|
|
6
|
+
require 'rails-i18n'
|
|
7
|
+
require 'turbolinks'
|
|
8
|
+
require 'authlogic'
|
|
9
|
+
require 'bootstrap'
|
|
10
|
+
|
|
11
|
+
require 'will_paginate'
|
|
12
|
+
require 'api-pagination'
|
|
13
|
+
require 'font-awesome-rails'
|
|
14
|
+
require 'jquery-rails'
|
|
15
|
+
require 'jquery-ui-rails'
|
|
16
|
+
require 'rdiscount'
|
|
17
|
+
require 'sortable-table'
|
|
18
|
+
require 'paperclip'
|
|
19
|
+
require 'awesome_nested_set'
|
|
20
|
+
require 'acts_as_list'
|
|
21
|
+
require 'bootstrap_form'
|
|
22
|
+
require 'the_sortable_tree'
|
|
23
|
+
require 'bootstrap-datepicker-rails'
|
|
24
|
+
require 'wicked_pdf'
|
|
25
|
+
require 'swagger/blocks'
|
|
26
|
+
|
|
27
|
+
module Symphonia
|
|
28
|
+
|
|
29
|
+
class Engine < ::Rails::Engine
|
|
30
|
+
isolate_namespace Symphonia
|
|
31
|
+
|
|
32
|
+
config.generators do |g|
|
|
33
|
+
g.test_framework :rspec, fixture: false
|
|
34
|
+
# g.fixture_replacement :factory_girl, dir: 'spec/factories'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Rails 5
|
|
38
|
+
# ActionController::Base.class_eval do
|
|
39
|
+
# include Symphonia::ApplicationController
|
|
40
|
+
# end
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
initializer :symphonia_extensions do
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# ActiveSupport::Reloader.to_prepare do
|
|
47
|
+
# ::ApplicationController.send :helper, Symphonia::ApplicationHelper
|
|
48
|
+
# ::ApplicationMailer.send :helper, Symphonia::ApplicationHelper
|
|
49
|
+
# BootstrapForm::FormBuilder.prepend(Symphonia::FormBuilder)
|
|
50
|
+
# end
|
|
51
|
+
|
|
52
|
+
initializer :symphonia_setup do |_app|
|
|
53
|
+
Mime::Type.register 'application/pdf', :pdf
|
|
54
|
+
config.i18n.available_locales ||= %i[cs en]
|
|
55
|
+
config.i18n.default_locale = :cs
|
|
56
|
+
|
|
57
|
+
WillPaginate.per_page = 20
|
|
58
|
+
|
|
59
|
+
Symphonia.configure do |config|
|
|
60
|
+
config.after_login_path = ->(h) { h.symphonia.user_current_path }
|
|
61
|
+
config.allow_registrations = true
|
|
62
|
+
config.default_locale = :cs
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
initializer :append_migrations do |app|
|
|
68
|
+
if app.root.to_s != root.to_s && app.root != root.join("spec/dummy")
|
|
69
|
+
config.paths['db/migrate'].expanded.each do |expanded_path|
|
|
70
|
+
app.config.paths['db/migrate'] << expanded_path
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# include helpers
|
|
76
|
+
initializer :load_helper, before: :load_config_initializers do |app|
|
|
77
|
+
# config.active_record.raise_in_transactional_callbacks = false
|
|
78
|
+
if Rails.env.development?
|
|
79
|
+
config.action_mailer.default_url_options ||= { host: 'symphonia.app' }
|
|
80
|
+
config.action_mailer.preview_path = "{#{app.root.join('spec/mailers/previews')},#{root.join('spec/mailers/previews')}}"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
initializer :assets do |_app|
|
|
85
|
+
if defined?(::Ckeditor)
|
|
86
|
+
config.assets.precompile << 'ckeditor/**/*'
|
|
87
|
+
config.assets.precompile << 'symphonia/symphonia_ckeditor.js'
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
initializer :symphonia_general_permissions do |_app|
|
|
92
|
+
Symphonia::Permissions.map do |m|
|
|
93
|
+
m.register(:view_users).add(:users, %i[index show])
|
|
94
|
+
m.register(:manager_users).add(:users, %i[create update destroy new edit])
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
initializer :wicked_pdf do |_app|
|
|
100
|
+
WickedPdf.config = {
|
|
101
|
+
layout: 'application.pdf',
|
|
102
|
+
print_media_type: true,
|
|
103
|
+
viewport_size: '1280x800', zoom: 0.7, dpi: 300
|
|
104
|
+
}
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
initializer :api_paginate do
|
|
108
|
+
ApiPagination.configure do |config|
|
|
109
|
+
# If you have both gems included, you can choose a paginator.
|
|
110
|
+
config.paginator = :will_paginate
|
|
111
|
+
|
|
112
|
+
# By default, this is set to 'Total'
|
|
113
|
+
config.total_header = 'X-Total'
|
|
114
|
+
|
|
115
|
+
# By default, this is set to 'Per-Page'
|
|
116
|
+
config.per_page_header = 'X-Per-Page'
|
|
117
|
+
|
|
118
|
+
# Optional: set this to add a header with the current page number.
|
|
119
|
+
config.page_header = 'X-Page'
|
|
120
|
+
|
|
121
|
+
# Optional: what parameter should be used to set the page option
|
|
122
|
+
# config.page_param = :page
|
|
123
|
+
# # or
|
|
124
|
+
# config.page_param do |params|
|
|
125
|
+
# params[:page][:number]
|
|
126
|
+
# end
|
|
127
|
+
#
|
|
128
|
+
# # Optional: what parameter should be used to set the per page option
|
|
129
|
+
# config.per_page_param = :per_page
|
|
130
|
+
# # or
|
|
131
|
+
# config.per_page_param do |params|
|
|
132
|
+
# params[:page][:size]
|
|
133
|
+
# end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
module Symphonia
|
|
2
|
+
class FormBuilder < ::BootstrapForm::FormBuilder
|
|
3
|
+
|
|
4
|
+
def error_messages
|
|
5
|
+
if object.respond_to?(:errors) && object.errors.any?
|
|
6
|
+
list = content_tag(:p, I18n.t('activerecord.errors.template.body')).html_safe
|
|
7
|
+
list += content_tag(:ul) do
|
|
8
|
+
object.errors.full_messages.collect do |error|
|
|
9
|
+
content_tag(:li, error)
|
|
10
|
+
end.join.html_safe
|
|
11
|
+
end
|
|
12
|
+
content_tag(:div, list, class: 'error_explanation')
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def calendar_field(name, options = {})
|
|
17
|
+
options[:data] ||= {} #{'date-clear-btn': true, 'date-format': 'yyyy-mm-dd'}
|
|
18
|
+
options[:data][:'date-clear-btn'] ||= true
|
|
19
|
+
# options[:data][:'date-format'] ||= 'yyyy-mm-dd'
|
|
20
|
+
text_field(name, options.merge({
|
|
21
|
+
class: 'form-control datepicker',
|
|
22
|
+
append: @template.fa_icon('calendar')
|
|
23
|
+
}))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# def form_group_builder(method, options, html_options = nil)
|
|
27
|
+
# options.symbolize_keys!
|
|
28
|
+
# html_options.symbolize_keys! if html_options
|
|
29
|
+
#
|
|
30
|
+
# # Add control_class; allow it to be overridden by :control_class option
|
|
31
|
+
# css_options = html_options || options
|
|
32
|
+
# control_classes = css_options.delete(:control_class) { control_class }
|
|
33
|
+
# css_options[:class] = [control_classes, css_options[:class]].compact.join(" ")
|
|
34
|
+
# css_options[:class] << " is-invalid" if has_error?(method)
|
|
35
|
+
#
|
|
36
|
+
# options = convert_form_tag_options(method, options) if acts_like_form_tag
|
|
37
|
+
#
|
|
38
|
+
# wrapper_class = css_options.delete(:wrapper_class)
|
|
39
|
+
# wrapper_options = css_options.delete(:wrapper)
|
|
40
|
+
# help = options.delete(:help)
|
|
41
|
+
# icon = options.delete(:icon)
|
|
42
|
+
# label_col = options.delete(:label_col)
|
|
43
|
+
# control_col = options.delete(:control_col)
|
|
44
|
+
# layout = get_group_layout(options.delete(:layout))
|
|
45
|
+
# form_group_options = {
|
|
46
|
+
# id: options[:id],
|
|
47
|
+
# help: help,
|
|
48
|
+
# icon: icon,
|
|
49
|
+
# label_col: label_col,
|
|
50
|
+
# control_col: control_col,
|
|
51
|
+
# layout: layout,
|
|
52
|
+
# class: wrapper_class
|
|
53
|
+
# }
|
|
54
|
+
#
|
|
55
|
+
# if wrapper_options.is_a?(Hash)
|
|
56
|
+
# form_group_options.merge!(wrapper_options)
|
|
57
|
+
# end
|
|
58
|
+
#
|
|
59
|
+
# unless options.delete(:skip_label)
|
|
60
|
+
# if options[:label].is_a?(Hash)
|
|
61
|
+
# label_text = options[:label].delete(:text)
|
|
62
|
+
# label_class = options[:label].delete(:class)
|
|
63
|
+
# options.delete(:label)
|
|
64
|
+
# end
|
|
65
|
+
# label_class ||= options.delete(:label_class)
|
|
66
|
+
# label_class = hide_class if options.delete(:hide_label)
|
|
67
|
+
#
|
|
68
|
+
# if options[:label].is_a?(String)
|
|
69
|
+
# label_text ||= options.delete(:label)
|
|
70
|
+
# end
|
|
71
|
+
#
|
|
72
|
+
# form_group_options.merge!(label: {
|
|
73
|
+
# text: label_text,
|
|
74
|
+
# class: label_class,
|
|
75
|
+
# skip_required: options.delete(:skip_required),
|
|
76
|
+
# required: options.delete(:required)
|
|
77
|
+
# })
|
|
78
|
+
# end
|
|
79
|
+
#
|
|
80
|
+
# form_group(method, form_group_options) do
|
|
81
|
+
# yield
|
|
82
|
+
# end
|
|
83
|
+
# end
|
|
84
|
+
|
|
85
|
+
def label_text(name, options)
|
|
86
|
+
name = name.to_s.remove(/_id$/)
|
|
87
|
+
|
|
88
|
+
if label_errors && error?(name)
|
|
89
|
+
(options[:text] || object.class.human_attribute_name(name)).to_s.concat(" #{get_error_messages(name)}")
|
|
90
|
+
else
|
|
91
|
+
options[:text]
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
# def generate_label(id, name, options, custom_label_col, group_layout)
|
|
95
|
+
# return if options.blank?
|
|
96
|
+
# # id is the caller's options[:id] at the only place this method is called.
|
|
97
|
+
# # The options argument is a small subset of the options that might have
|
|
98
|
+
# # been passed to generate_label's caller, and definitely doesn't include
|
|
99
|
+
# # :id.
|
|
100
|
+
# options[:for] = id if acts_like_form_tag
|
|
101
|
+
# classes = [options[:class]]
|
|
102
|
+
#
|
|
103
|
+
# if layout_horizontal?(group_layout)
|
|
104
|
+
# classes << "col-form-label"
|
|
105
|
+
# classes << (custom_label_col || label_col)
|
|
106
|
+
# elsif layout_inline?(group_layout)
|
|
107
|
+
# classes << "mr-sm-2"
|
|
108
|
+
# end
|
|
109
|
+
#
|
|
110
|
+
# xname = name.to_s.remove(/_id$/)
|
|
111
|
+
#
|
|
112
|
+
# case options.delete(:required)
|
|
113
|
+
# when true
|
|
114
|
+
# classes << "required"
|
|
115
|
+
# when nil, :default
|
|
116
|
+
# classes << "required" if required_attribute?(object, name)
|
|
117
|
+
# end
|
|
118
|
+
#
|
|
119
|
+
# options[:class] = classes.compact.join(" ").strip
|
|
120
|
+
# options.delete(:class) if options[:class].empty?
|
|
121
|
+
#
|
|
122
|
+
# if label_errors && has_error?(name)
|
|
123
|
+
# error_messages = get_error_messages(name)
|
|
124
|
+
# label_text = (options[:text] || object.class.human_attribute_name(xname)).to_s.concat(" #{error_messages}")
|
|
125
|
+
# options[:class] = [options[:class], "text-danger"].compact.join(" ")
|
|
126
|
+
# label(name, label_text, options.except(:text))
|
|
127
|
+
# else
|
|
128
|
+
# label(name, options[:text], options.except(:text))
|
|
129
|
+
# end
|
|
130
|
+
# end
|
|
131
|
+
|
|
132
|
+
def error_class
|
|
133
|
+
'is-invalid'
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Symphonia
|
|
2
|
+
module MenuManager
|
|
3
|
+
@@mapper = {}
|
|
4
|
+
mattr_accessor :mapper
|
|
5
|
+
|
|
6
|
+
def self.menu(name)
|
|
7
|
+
return mapper[name.to_sym] || {}
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class << self
|
|
11
|
+
def map(menu_name)
|
|
12
|
+
mapper[menu_name] ||= {}
|
|
13
|
+
if block_given?
|
|
14
|
+
yield mapper[menu_name]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def clear(menu_name)
|
|
19
|
+
!mapper.delete(menu_name.to_sym).nil?
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
module Symphonia
|
|
2
|
+
module ModelAttributes
|
|
3
|
+
class Attribute
|
|
4
|
+
|
|
5
|
+
attr_reader :name, :options
|
|
6
|
+
attr_reader :format_options, :sort_column
|
|
7
|
+
attr_accessor :filter
|
|
8
|
+
|
|
9
|
+
def initialize(name, klass, options, formatter)
|
|
10
|
+
@name = name
|
|
11
|
+
@klass = klass
|
|
12
|
+
@formatter = formatter
|
|
13
|
+
@options = options
|
|
14
|
+
@format_options = {}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def title
|
|
18
|
+
@klass.human_attribute_name(@name.to_s.remove(/_id$/), @options[:i18n] || {})
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def value(entity)
|
|
22
|
+
entity.send(name)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def format(view, entity, options={})
|
|
26
|
+
@format_options = options
|
|
27
|
+
if @formatter.is_a?(Proc)
|
|
28
|
+
@formatter.call(view, self, entity).to_s
|
|
29
|
+
else
|
|
30
|
+
format_value(view, value(entity), entity)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def sort=(sort_options)
|
|
35
|
+
t = @klass.arel_table
|
|
36
|
+
@sort = true
|
|
37
|
+
case sort_options
|
|
38
|
+
when false
|
|
39
|
+
@sort = false
|
|
40
|
+
when Symbol, Array
|
|
41
|
+
sort = Array(sort_options).collect { |i| t[i] }
|
|
42
|
+
asc_desc = { asc: sort.map { |i| i.asc.to_sql }.join(','), desc: sort.map { |i| i.desc.to_sql }.join(',') }
|
|
43
|
+
@sort_column = SortableTable::SortColumnCustomDefinition.new(@name, asc_desc)
|
|
44
|
+
when String
|
|
45
|
+
asc_desc = { asc: sort_options + ' ASC', desc: sort_options + ' DESC' }
|
|
46
|
+
@sort_column = SortableTable::SortColumnCustomDefinition.new(@name, asc_desc)
|
|
47
|
+
else
|
|
48
|
+
raise "Undefined `sort_options` type: #{sort_options.class.name}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def sort?
|
|
53
|
+
@sort
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def filter?
|
|
57
|
+
!!filter
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def default?
|
|
61
|
+
!!@options[:default]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def format_value(_view, value, _entity)
|
|
67
|
+
value.to_s
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class DecimalAttribute < Attribute
|
|
73
|
+
def format_value(view, value, entity)
|
|
74
|
+
view.format_price(value)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
class EnumAttribute < Attribute
|
|
79
|
+
# TODO: @klass.name || @klass.base_class.name || entity.class.name
|
|
80
|
+
def format_value(view, value, entity)
|
|
81
|
+
view.t("#{@klass.name.underscore}.#{name.to_s.pluralize}.#{value}", format_options)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
class LinkAttribute < Attribute
|
|
86
|
+
def format_value(view, value, entity)
|
|
87
|
+
view.link_to value.to_s, entity, format_options
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
class MailAttribute < Attribute
|
|
92
|
+
def format_value(view, value, entity)
|
|
93
|
+
view.mail_to value.to_s, value.to_s, format_options
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
class ReferenceAttribute < Attribute
|
|
98
|
+
|
|
99
|
+
def initialize(name, klass, options, formatter)
|
|
100
|
+
super
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def title
|
|
104
|
+
@klass.human_attribute_name(@klass.reflect_on_association(name).foreign_key, @options[:i18n] || {})
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def format_value(view, value, entity)
|
|
108
|
+
view.link_to value.to_s, value, format_options
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
class BooleanAttribute < Attribute
|
|
113
|
+
def format_value(view, value, entity)
|
|
114
|
+
if value.to_boolean
|
|
115
|
+
view.icon('true', view.t(:true))
|
|
116
|
+
else
|
|
117
|
+
view.icon('false', view.t(:false))
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
class DateAttribute < Attribute
|
|
123
|
+
def format_value(view, value, entity)
|
|
124
|
+
value && view.l(value.to_date, format_options)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
class DateTimeAttribute < Attribute
|
|
129
|
+
def format_value(view, value, entity)
|
|
130
|
+
value && view.l(value, format_options)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
class DatetimeAttribute < DateTimeAttribute
|
|
134
|
+
# alias
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|