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,168 @@
|
|
1
|
+
module Symphonia
|
2
|
+
class UsersController < ApplicationController
|
3
|
+
include Swagger::Blocks
|
4
|
+
|
5
|
+
swagger_path '/admin/users/{id}.json' do
|
6
|
+
operation :get do
|
7
|
+
key :summary, 'Find User by ID'
|
8
|
+
key :description, 'Returns a single user if the user has access'
|
9
|
+
# key :operationId, 'findPetById'
|
10
|
+
# key :tags, [
|
11
|
+
# 'pet'
|
12
|
+
# ]
|
13
|
+
parameter do
|
14
|
+
key :name, :id
|
15
|
+
key :in, :path
|
16
|
+
key :description, 'ID of user to fetch'
|
17
|
+
key :required, true
|
18
|
+
key :type, :integer
|
19
|
+
key :format, :int64
|
20
|
+
end
|
21
|
+
extend Symphonia::Swagger::Responses
|
22
|
+
response 200 do
|
23
|
+
key :description, 'user response'
|
24
|
+
schema do
|
25
|
+
key :'$ref', :User
|
26
|
+
end
|
27
|
+
end
|
28
|
+
# response :default do
|
29
|
+
# key :description, 'unexpected error'
|
30
|
+
# schema do
|
31
|
+
# key :'$ref', :ErrorModel
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
helper Symphonia::RendererHelper
|
38
|
+
|
39
|
+
before_action :find_user, except: %i[index new create show]
|
40
|
+
before_action :authorize, except: [:show]
|
41
|
+
before_action -> { menu_item(:my_account) }, only: %i[current edit_current update_current]
|
42
|
+
|
43
|
+
def index
|
44
|
+
@query = Symphonia::User.query.new
|
45
|
+
@query.from_params params
|
46
|
+
@entities = @query.entities
|
47
|
+
respond_to do |format|
|
48
|
+
format.html do
|
49
|
+
@entities = @entities.page(params[:page])
|
50
|
+
render layout: !request.xhr?
|
51
|
+
end
|
52
|
+
format.json { render json: @entities.all, only: %i[id]+Symphonia::User.registered_attributes.keys }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def show
|
57
|
+
@user = Symphonia::User.find(params[:id]) if params[:id]
|
58
|
+
@user ||= Symphonia::User.current
|
59
|
+
authorize
|
60
|
+
respond_to do |format|
|
61
|
+
format.html
|
62
|
+
format.json { render json: @user, except: %w[crypted_password password_salt persistence_token perishable_token] }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def new
|
67
|
+
@user = Symphonia::User.new
|
68
|
+
@roles = Symphonia::Role.sorted
|
69
|
+
respond_to do |format|
|
70
|
+
format.html
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def create
|
75
|
+
@user = Symphonia::User.new(user_params)
|
76
|
+
respond_to do |format|
|
77
|
+
if @user.save
|
78
|
+
format.html { redirect_to @user, notice: t(:text_created) }
|
79
|
+
format.xml { render xml: @user, status: :created, location: @user }
|
80
|
+
format.json { render json: @user, status: :created, location: @user }
|
81
|
+
else
|
82
|
+
format.html do
|
83
|
+
@roles = Symphonia::Role.sorted
|
84
|
+
render action: 'new'
|
85
|
+
end
|
86
|
+
format.xml { render xml: @user.errors, status: :unprocessable_entity }
|
87
|
+
format.json { render json: @user.errors, status: :unprocessable_entity }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def edit
|
93
|
+
@roles = Role.all
|
94
|
+
end
|
95
|
+
|
96
|
+
def update
|
97
|
+
@user.attributes = user_params
|
98
|
+
@user.admin = params[:admin] if params[:admin] && Symphonia::User.current.admin?
|
99
|
+
if params[:role_id].present? && Symphonia::User.current.admin?
|
100
|
+
@role = Role.find(params[:role_id])
|
101
|
+
@user.role = @role
|
102
|
+
end
|
103
|
+
respond_to do |format|
|
104
|
+
@user.edited_by = current_user
|
105
|
+
@user.edited_at = DateTime.now
|
106
|
+
if @user.save
|
107
|
+
format.html { redirect_back_or_default user_path(@user), notice: t(:text_updated) }
|
108
|
+
format.any(:json ,:xml) { head :no_content }
|
109
|
+
else
|
110
|
+
format.html do
|
111
|
+
@roles = Symphonia::Role.all
|
112
|
+
render action: 'edit'
|
113
|
+
end
|
114
|
+
format.xml { render xml: @user.errors, status: :unprocessable_entity }
|
115
|
+
format.json { render json: @user.errors, status: :unprocessable_entity }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def destroy
|
121
|
+
@user.destroy
|
122
|
+
|
123
|
+
respond_to do |format|
|
124
|
+
format.html { redirect_to params[:back_url] || users_url }
|
125
|
+
format.js { render js: "Symphonia.filters.removeRow('#{view_context.dom_id(@user)}')"}
|
126
|
+
format.json { head :no_content }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def archive
|
131
|
+
@user.archive!
|
132
|
+
respond_to do |format|
|
133
|
+
format.html { redirect_to params[:back_url] || users_url }
|
134
|
+
format.json { head :no_content }
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def unarchive
|
139
|
+
Notifier.user_change_to_active(@user).deliver_later
|
140
|
+
@user.unarchive!
|
141
|
+
|
142
|
+
respond_to do |format|
|
143
|
+
format.html { redirect_to params[:back_url] || users_url }
|
144
|
+
format.xml { head :no_content }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
def find_user
|
151
|
+
@user = Symphonia::User.find(params[:id])
|
152
|
+
end
|
153
|
+
|
154
|
+
def authorize
|
155
|
+
if User.current.id == @user.try!(:id)
|
156
|
+
true
|
157
|
+
else
|
158
|
+
super
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def user_params
|
163
|
+
allowed = [:login, :first_name, :last_name, :password, :password_confirmation, :email, :mail, preference_ids: []]
|
164
|
+
allowed.concat(%i[admin role_id]) if Symphonia::User.current.admin?
|
165
|
+
params.require(:user).permit(allowed)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,422 @@
|
|
1
|
+
# require 'symphonia/bootstrap_link_render'
|
2
|
+
module Symphonia
|
3
|
+
module ApplicationHelper
|
4
|
+
include FontAwesome::Rails::IconHelper
|
5
|
+
include FormHelper
|
6
|
+
|
7
|
+
def bootstrap_class_for(flash_type)
|
8
|
+
case flash_type.to_sym
|
9
|
+
when :notice
|
10
|
+
'alert-success'
|
11
|
+
when :error, :alert
|
12
|
+
'alert-danger'
|
13
|
+
when :warning
|
14
|
+
'alert-warning'
|
15
|
+
when :info
|
16
|
+
'alert-info'
|
17
|
+
else
|
18
|
+
flash_type.to_s
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Renders flash messages
|
23
|
+
def render_flash_messages(flash_messages = nil)
|
24
|
+
s = ''
|
25
|
+
Array(flash_messages || flash).each do |type, message|
|
26
|
+
s << content_tag(:div, class: "alert #{bootstrap_class_for(type)}") do
|
27
|
+
content_tag(:button, '', class: 'fa fa-times-circle-o close', data: { dismiss: 'alert' }) + Array.wrap(message).collect { |m| fa_icon(type, text: m) }.join("<br>").html_safe
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
return s.html_safe
|
32
|
+
end
|
33
|
+
|
34
|
+
def render_menu(menu, options = {})
|
35
|
+
s = ''
|
36
|
+
Symphonia::MenuManager.menu(menu).each do |name, item|
|
37
|
+
s << render_menu_node(name, item).to_s
|
38
|
+
end
|
39
|
+
options[:container_class] ||= 'mr-auto'
|
40
|
+
|
41
|
+
return content_tag(:ul, s.html_safe, itemscope: '', itemtype: 'http://data-vocabulary.org/BreadcrumbList', class: "navbar-nav #{options[:container_class]}", id: menu.to_s)
|
42
|
+
end
|
43
|
+
|
44
|
+
def render_menu_node(menu, item, options = {})
|
45
|
+
condition = item[:if] ? item[:if].call : true
|
46
|
+
selected = @menu_item.to_sym == menu
|
47
|
+
label = case item[:label].class.name
|
48
|
+
when 'NilClass'
|
49
|
+
' '.html_safe
|
50
|
+
when 'String'
|
51
|
+
item[:label]
|
52
|
+
when 'Symbol'
|
53
|
+
t(item[:label])
|
54
|
+
when 'Proc'
|
55
|
+
item[:label].call(controller)
|
56
|
+
else
|
57
|
+
raise "MenuManager error: Label is unknown type: #{item[:label].class}"
|
58
|
+
end
|
59
|
+
if item[:children].blank?
|
60
|
+
return content_tag(:li, render_menu_link(item, label, options), class: "nav-item #{menu} #{'active' if selected} #{options[:class]}", id: item[:id]) if condition
|
61
|
+
else
|
62
|
+
children = ''
|
63
|
+
item[:children].each do |child, subitem|
|
64
|
+
children << render_menu_node(menu, subitem, class: 'dropdown-item').to_s
|
65
|
+
end
|
66
|
+
unless children.blank?
|
67
|
+
return content_tag(:li, class: "nav-item dropdown #{menu}") do
|
68
|
+
concat render_menu_link(item.merge({ class: 'dropdown-toggle', data: { toggle: 'dropdown' } }), label, { is_submenu: true })
|
69
|
+
concat content_tag(:ul, children.html_safe, class: 'dropdown-menu')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def render_menu_link(item, label, _options = {})
|
76
|
+
url = case item[:url].class.name
|
77
|
+
when 'Symbol'
|
78
|
+
if item[:url].to_s.include?('.')
|
79
|
+
endpoint, path = item[:url].to_s.split('.')
|
80
|
+
send(endpoint).send(path)
|
81
|
+
else
|
82
|
+
main_app.send item[:url]
|
83
|
+
end
|
84
|
+
when 'Proc'
|
85
|
+
item[:url].call(self)
|
86
|
+
else
|
87
|
+
item[:url]
|
88
|
+
end
|
89
|
+
link_to(
|
90
|
+
(content_tag(:i, '', class: "#{item[:icon]}") + "\n" + content_tag(:span, label, itemprop: 'title')).html_safe,
|
91
|
+
url,
|
92
|
+
class: "nav-link #{item[:class]}",
|
93
|
+
data: item[:data],
|
94
|
+
method: item[:method],
|
95
|
+
itemprop: 'url'
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
def html_title(*args)
|
100
|
+
if args.empty?
|
101
|
+
title = @html_title || []
|
102
|
+
title << t(:meta_title)
|
103
|
+
title.reject(&:blank?).join(' — ')
|
104
|
+
else
|
105
|
+
@html_title ||= []
|
106
|
+
@html_title += args
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def html_description(*args)
|
111
|
+
if args.empty?
|
112
|
+
desc = @html_description
|
113
|
+
desc ||= t(:meta_description)
|
114
|
+
desc.to_s
|
115
|
+
else
|
116
|
+
@html_description ||= []
|
117
|
+
@html_description += args
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def title(*args, &block)
|
122
|
+
options = args.extract_options!
|
123
|
+
header = args.shift
|
124
|
+
small = args.shift || ''
|
125
|
+
header_text = if header.is_a?(Symbol)
|
126
|
+
t(header, default: header.to_s.humanize)
|
127
|
+
else
|
128
|
+
header.to_s.dup
|
129
|
+
end
|
130
|
+
if @symphonia_modal_dialog
|
131
|
+
ActiveSupport::Deprecation.warn "@symphonia_modal_dialog is no used anymore !"
|
132
|
+
@symphonia_modal_dialog.title ||= header_text
|
133
|
+
''
|
134
|
+
else
|
135
|
+
html_title(header_text.dup)
|
136
|
+
header_text << "\n" + content_tag(:small, small, class: 'text-muted') if small.present?
|
137
|
+
s = ''
|
138
|
+
if options[:back] && !request.xhr?
|
139
|
+
back_url = options[:back] unless options[:back].is_a? TrueClass
|
140
|
+
s << link_to_back(back_url)
|
141
|
+
end
|
142
|
+
s << capture(&block).to_s if block_given?
|
143
|
+
header_tag = content_tag request.xhr? && :h5 || :h1, id: 'page_header', class: s.present? && "col-6" || nil do
|
144
|
+
header_text.html_safe
|
145
|
+
end
|
146
|
+
return header_tag if s.blank?
|
147
|
+
|
148
|
+
content_tag :div, class: "row" do
|
149
|
+
header_tag + content_tag(:div, s.html_safe, class: "col-6 text-right")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
alias_method :page_header, :title
|
155
|
+
|
156
|
+
def render_no_data(message = nil)
|
157
|
+
content_tag(:div, message || t(:text_no_data), class: 'nodata')
|
158
|
+
end
|
159
|
+
|
160
|
+
def content_for(name, content = nil, &block)
|
161
|
+
@has_content ||= {}
|
162
|
+
@has_content[name] = true
|
163
|
+
super(name, content, &block)
|
164
|
+
end
|
165
|
+
|
166
|
+
def has_content?(name)
|
167
|
+
!!(@has_content && @has_content[name])
|
168
|
+
end
|
169
|
+
|
170
|
+
def format_text(text, _options = {})
|
171
|
+
return '' if text.nil?
|
172
|
+
|
173
|
+
markdown = RDiscount.new(text, :smart, :filter_html)
|
174
|
+
markdown.to_html.html_safe
|
175
|
+
end
|
176
|
+
|
177
|
+
def format_html(text)
|
178
|
+
content_tag(:div, (defined?(Ckeditor) ? text.html_safe : format_text(text)), class: 'formatted-text')
|
179
|
+
end
|
180
|
+
|
181
|
+
def format_price(value, options = {})
|
182
|
+
number_to_currency(value, { precision: 1, strip_insignificant_zeros: true }.merge(options))
|
183
|
+
end
|
184
|
+
|
185
|
+
def multiselect_toggler(id = nil)
|
186
|
+
link_to(fa_icon(:plus), 'javascript:void(0);', onclick: "toggleMultiSelect(#{id || 'this'});return false", class: 'btn fa fa-border')
|
187
|
+
end
|
188
|
+
|
189
|
+
def link_to_back(url = nil)
|
190
|
+
link_to(icon(:back, t(:button_back)), (params[:back_url] || url || :back), class: 'btn btn-link back')
|
191
|
+
end
|
192
|
+
|
193
|
+
def link_to_new_entity(options = {})
|
194
|
+
return '' unless User.current.allowed_to?(:"manage_#{controller_name}")
|
195
|
+
|
196
|
+
anchor = options.has_key?(:anchor) ? options.delete(:anchor) : 'page_header'
|
197
|
+
label = options.delete(:label) || t("label_#{controller_name.singularize}_new")
|
198
|
+
url = options.delete(:url) || new_polymorphic_path(controller_name.singularize, anchor: anchor)
|
199
|
+
link = link_to(fa_icon('add', text: label), url, { class: 'btn btn-primary' }.merge(options))
|
200
|
+
|
201
|
+
# content_tag(:div, link, class: 'contextual')
|
202
|
+
end
|
203
|
+
|
204
|
+
# change the default link renderer for will_paginate
|
205
|
+
def will_paginate(collection_or_options = nil, options = {})
|
206
|
+
if collection_or_options.is_a? Hash
|
207
|
+
options, collection_or_options = collection_or_options, nil
|
208
|
+
end
|
209
|
+
unless options[:renderer]
|
210
|
+
options = options.merge renderer: Symphonia::BootstrapLinkRender
|
211
|
+
end
|
212
|
+
options[:query] ||= @query if @query
|
213
|
+
super *[collection_or_options, options].compact
|
214
|
+
end
|
215
|
+
|
216
|
+
def ckeditor_for(field_id, options = {})
|
217
|
+
return '' unless !!defined?(Ckeditor)
|
218
|
+
|
219
|
+
inline = options.delete(:inline)
|
220
|
+
opts = options.inject({}) do |mem, var|
|
221
|
+
key = var[0].to_s.camelcase(:lower)
|
222
|
+
key[0].downcase!
|
223
|
+
mem[key] = var[1]
|
224
|
+
|
225
|
+
mem
|
226
|
+
end
|
227
|
+
opts['toolbar'] ||= 'Basic'
|
228
|
+
# opts['customConfig'] ||= 'Basic'
|
229
|
+
js = if inline
|
230
|
+
"CKEDITOR.inline('#{field_id}', {toolbar: 'Basic'});"
|
231
|
+
else
|
232
|
+
"
|
233
|
+
var ta_editor = CKEDITOR.instances['#{field_id}'];
|
234
|
+
if (ta_editor) {CKEDITOR.remove(ta_editor);}
|
235
|
+
CKEDITOR.replace('#{field_id}', #{opts.to_json.html_safe});
|
236
|
+
"
|
237
|
+
end
|
238
|
+
javascript_tag("$(document).ready(function() {#{js.html_safe}})".html_safe)
|
239
|
+
end
|
240
|
+
|
241
|
+
def icon(fa, text = nil)
|
242
|
+
fa_icon(fa, text && { text: content_tag(:span, text, class: 'd-none d-sm-inline') } || {})
|
243
|
+
end
|
244
|
+
|
245
|
+
def render_symphonia_dialog(*args, &block)
|
246
|
+
ActiveSupport::Deprecation.warn "Use `render_modal` instead"
|
247
|
+
options = args.extract_options!
|
248
|
+
title = options[:title] || args.shift # first arg possible `title`
|
249
|
+
body = args.shift
|
250
|
+
options[:form_disabled] = true
|
251
|
+
size = options.delete(:size)
|
252
|
+
size ||= '90%' if options.delete(:large)
|
253
|
+
if size.to_s.match(%r(^\d+$))
|
254
|
+
size = size.to_s + '%'
|
255
|
+
end
|
256
|
+
@symphonia_modal_dialog = SymphoniaModalDialog.new(self, options)
|
257
|
+
@symphonia_modal_dialog.size = size
|
258
|
+
if block_given?
|
259
|
+
yield @symphonia_modal_dialog
|
260
|
+
else
|
261
|
+
raise ArgumentError if body.nil?
|
262
|
+
end
|
263
|
+
@symphonia_modal_dialog.title ||= title
|
264
|
+
if @symphonia_modal_dialog.body.blank?
|
265
|
+
if body.is_a?(Hash)
|
266
|
+
body.merge!(formats: [:html])
|
267
|
+
else
|
268
|
+
body = { partial: body, formats: [:html] }
|
269
|
+
end
|
270
|
+
@symphonia_modal_dialog.body = render(body)
|
271
|
+
end
|
272
|
+
html = @symphonia_modal_dialog.to_html
|
273
|
+
if options[:render_only]
|
274
|
+
html
|
275
|
+
else
|
276
|
+
js = %Q(
|
277
|
+
$('##{@symphonia_modal_dialog.modal_id}').modal('hide').remove();
|
278
|
+
$('body').append('#{j html}');
|
279
|
+
showModal('##{@symphonia_modal_dialog.modal_id}');
|
280
|
+
$("##{@symphonia_modal_dialog.modal_id} .modal-dialog input:text").first().focus();
|
281
|
+
$("##{@symphonia_modal_dialog.modal_id} .modal-dialog .modal-body div.buttons").remove();
|
282
|
+
)
|
283
|
+
js.concat("$('##{@symphonia_modal_dialog.modal_id} .modal-dialog').css({width: '#{size}'});") if size.present?
|
284
|
+
js.html_safe
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
# def render_modal_dialog(show = true, options = {}, &block)
|
289
|
+
# tags = SymphoniaModalDialog.new(self, options)
|
290
|
+
# yield tags if block_given?
|
291
|
+
# html = tags.to_html
|
292
|
+
# if show
|
293
|
+
# "$('##{tags.modal_id}').remove();$('body').append('#{j html}'); showModal('##{tags.modal_id}');".html_safe
|
294
|
+
# else
|
295
|
+
# html
|
296
|
+
# end
|
297
|
+
# end
|
298
|
+
|
299
|
+
class SymphoniaModalDialog
|
300
|
+
|
301
|
+
attr_writer :title, :body, :footer
|
302
|
+
attr_reader :modal_id, :title
|
303
|
+
|
304
|
+
attr_accessor :size
|
305
|
+
|
306
|
+
def initialize(controller, options = {})
|
307
|
+
@c = controller
|
308
|
+
@title = options.delete(:title)
|
309
|
+
@modal_id = options.delete(:id) || 'modal-dialog'
|
310
|
+
@form_options = options.delete(:form_options) || {}
|
311
|
+
@options = options
|
312
|
+
end
|
313
|
+
|
314
|
+
alias_attribute :id, :modal_id
|
315
|
+
|
316
|
+
def to_html
|
317
|
+
html = "<div id='#{@modal_id}' style='' class='modal fade' role='dialog'><div class='modal-dialog #{'modal-lg' if size.present?}'><div class='modal-content'>"
|
318
|
+
html << @c.content_tag(:div, class: 'modal-header') do
|
319
|
+
@c.content_tag(:button, '', class: 'close fa fa-times', data: { dismiss: 'modal' }, 'aria-hidden' => true) + @c.content_tag(:h4, @title, class: 'modal-title') + @header.to_s
|
320
|
+
end
|
321
|
+
content = @c.content_tag(:div, @c.content_tag(:div, body.html_safe, class: 'modal-content-inner-container container-fluid'), class: 'modal-body')
|
322
|
+
content << @c.content_tag(:div, footer.html_safe, class: 'modal-footer')
|
323
|
+
|
324
|
+
html << content.html_safe
|
325
|
+
html << '</div></div></div>'
|
326
|
+
html.html_safe
|
327
|
+
end
|
328
|
+
|
329
|
+
def header(&block)
|
330
|
+
if block_given?
|
331
|
+
@header = @c.capture(&block)
|
332
|
+
else
|
333
|
+
@header = (@header.is_a?(Proc) ? @header.call.to_s : @header.to_s)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
def body(&block)
|
338
|
+
if block_given?
|
339
|
+
@body = @c.capture(&block)
|
340
|
+
else
|
341
|
+
@body = (@body.is_a?(Proc) ? @body.call.to_s : @body.to_s)
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
def footer(&block)
|
346
|
+
if block_given?
|
347
|
+
@footer = @c.capture(&block)
|
348
|
+
else
|
349
|
+
@footer = (@footer.is_a?(Proc) ? @footer.call.to_s : @footer.to_s)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
def submit(name = nil, options = {})
|
354
|
+
name ||= @c.t(:button_save)
|
355
|
+
@footer = footer.to_s + @c.link_to(name, 'javascript:void(0)', { onclick: "$('##{@modal_id}').find('form').submit()", class: 'btn btn-primary' }.merge(options)).html_safe
|
356
|
+
end
|
357
|
+
|
358
|
+
end
|
359
|
+
|
360
|
+
# Example of use
|
361
|
+
# <%=
|
362
|
+
# table_header_tag_for(User) do |t|
|
363
|
+
# t.th :login
|
364
|
+
# t.th :email
|
365
|
+
# end
|
366
|
+
# %>
|
367
|
+
# options:
|
368
|
+
# => column : DB full name of column
|
369
|
+
#
|
370
|
+
# def table_header_tag_for(model, &block)
|
371
|
+
# tags = TableHeaderTag.new(model, self)
|
372
|
+
# yield tags
|
373
|
+
# tags.to_html
|
374
|
+
# end
|
375
|
+
#
|
376
|
+
# class TableHeaderTag
|
377
|
+
#
|
378
|
+
# attr_reader :view, :model
|
379
|
+
#
|
380
|
+
# def initialize(model, view)
|
381
|
+
# @model = model
|
382
|
+
# @tags = Array.new
|
383
|
+
# @view = view
|
384
|
+
# end
|
385
|
+
#
|
386
|
+
# def th(*args)
|
387
|
+
# options = args.extract_options!
|
388
|
+
# attribute = args.first
|
389
|
+
# label = args[1]
|
390
|
+
# raise ArgumentError if attribute.nil?
|
391
|
+
#
|
392
|
+
# sort_options = options.delete(:sort_options) || {}
|
393
|
+
# html_options = options.delete(:html_options) || {}
|
394
|
+
#
|
395
|
+
# label ||= @model.send(:human_attribute_name, attribute, options[:i18n] || {})
|
396
|
+
# @tags << @view.content_tag(:th, html_options) do
|
397
|
+
# if options[:sort] === false
|
398
|
+
# label
|
399
|
+
# else
|
400
|
+
# sort_options[:column] ||= options.delete(:column)
|
401
|
+
# sort_options[:column] ||= "#{@model.send(:table_name)}.#{attribute}"
|
402
|
+
# # @view.sortable_column(label, sort_options) # TODO: Rails 5 error
|
403
|
+
# label
|
404
|
+
# end
|
405
|
+
# end
|
406
|
+
#
|
407
|
+
# end
|
408
|
+
#
|
409
|
+
# def to_html
|
410
|
+
# @tags.join("\n").html_safe
|
411
|
+
# end
|
412
|
+
#
|
413
|
+
# end
|
414
|
+
|
415
|
+
# def render_share_buttons(url, name, options = {})
|
416
|
+
# options[:icon_css] ||= ''
|
417
|
+
# render(partial: 'common/share_links', locals: options.merge({ url: url, name: name }))
|
418
|
+
# end
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
#ApplicationHelper.send :include, Symphonia::ApplicationHelperExtension
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Symphonia
|
2
|
+
module BootstrapModalHelper
|
3
|
+
|
4
|
+
# Ruby shortcut for generate modals
|
5
|
+
#
|
6
|
+
# <%= render_modal title: t(:title) do %>
|
7
|
+
# <% render(template: 'path_to_template_or_partial', formats: [:html]) %>
|
8
|
+
# <% end %>
|
9
|
+
|
10
|
+
# template_or_partial example:
|
11
|
+
|
12
|
+
# <%= title(@entity, back: !request.xhr?) %>
|
13
|
+
#
|
14
|
+
# <%= symphonia_form_for(@entity, remote: request.xhr?) do |f| %>
|
15
|
+
#
|
16
|
+
# <%= render(partial: 'form', locals: { f: f }) %>
|
17
|
+
#
|
18
|
+
# <%= f.primary unless request.xhr? %>
|
19
|
+
# <% end -%>
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
#
|
24
|
+
def render_modal(options = {}, &block)
|
25
|
+
opts = options.slice(:id, :title, :submit, :large)
|
26
|
+
opts[:submit] = t(:button_submit) unless opts.has_key?(:submit)
|
27
|
+
|
28
|
+
id = options.delete(:id) || 'ad_hoc_modal'
|
29
|
+
|
30
|
+
|
31
|
+
script = <<SCRIPT
|
32
|
+
if (typeof(renderModal) == "undefined")
|
33
|
+
var renderModal = {}
|
34
|
+
if (renderModal["#{id}"])
|
35
|
+
renderModal["#{id}"].destroy();
|
36
|
+
|
37
|
+
renderModal["#{id}"] = new SymphoniaDialog("#{id}", #{raw opts.to_json});
|
38
|
+
renderModal["#{id}"].body.innerHTML = "#{j(capture(&block))}";
|
39
|
+
var submitButton = renderModal["#{id}"].body.querySelector("input[type=submit]")
|
40
|
+
if (submitButton)
|
41
|
+
submitButton.remove()
|
42
|
+
SCRIPT
|
43
|
+
unless opts[:title]
|
44
|
+
script.concat <<EOF
|
45
|
+
var title = document.getElementById(renderModal["#{id}"].id).querySelector("#page_header");
|
46
|
+
if (title) {
|
47
|
+
title.className = 'modal-title'; title.id = null;
|
48
|
+
$(renderModal["#{id}"].title).replaceWith($(title));
|
49
|
+
renderModal["#{id}"].title = title;
|
50
|
+
}
|
51
|
+
EOF
|
52
|
+
end
|
53
|
+
# script << %q{}
|
54
|
+
script << %Q{renderModal["#{id}"].show();} unless opts.has_key?(:render_only)
|
55
|
+
script.html_safe
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Symphonia
|
2
|
+
module FormHelper
|
3
|
+
|
4
|
+
def symphonia_form_for(object, options={}, &block)
|
5
|
+
options.reverse_merge!(builder: Symphonia::FormBuilder)
|
6
|
+
|
7
|
+
options = process_options(options)
|
8
|
+
|
9
|
+
unless options[:remote] && options[:local].nil?
|
10
|
+
options[:local] = true
|
11
|
+
end
|
12
|
+
if (as = options[:as])
|
13
|
+
options[:scope] ||= as
|
14
|
+
end
|
15
|
+
|
16
|
+
with_bootstrap_form_field_error_proc do
|
17
|
+
form_for(object, options, &block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# def symphonia_form_for(object, options = {}, &block)
|
22
|
+
# options.reverse_merge!({ builder: Symphonia::FormBuilder })
|
23
|
+
#
|
24
|
+
# options[:html] ||= {}
|
25
|
+
# options[:html][:role] ||= 'form'
|
26
|
+
#
|
27
|
+
# if options[:layout] == :inline
|
28
|
+
# options[:html][:class] = [options[:html][:class], 'form-inline'].compact.join(' ')
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# unless options[:remote] && options[:local].nil?
|
32
|
+
# options[:local] = true
|
33
|
+
# end
|
34
|
+
# if (as = options[:as])
|
35
|
+
# options[:scope] ||= as
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# temporarily_disable_field_error_proc do
|
39
|
+
# form_for(object, options, &block)
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# end
|
43
|
+
|
44
|
+
def symphonia_form_tag(options = {}, &block)
|
45
|
+
options[:acts_like_form_tag] = true
|
46
|
+
|
47
|
+
symphonia_form_for("", options, &block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|