symphonia 3.0.3 → 3.1.0

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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/app/assets/config/symphonia_manifest.js +5 -0
  4. data/app/assets/javascripts/symphonia/{application.js.erb → application.js} +0 -0
  5. data/app/controllers/base_controller.rb +4 -0
  6. data/app/controllers/symphonia/accounts_controller.rb +12 -11
  7. data/app/controllers/symphonia/users_controller.rb +2 -2
  8. data/app/helpers/symphonia/renderer_helper.rb +1 -2
  9. data/app/models/symphonia/user.rb +1 -0
  10. data/app/views/base/_form.html.erb +15 -0
  11. data/app/views/base/edit.html.erb +3 -0
  12. data/app/views/base/index.html.erb +5 -0
  13. data/app/views/base/new.html.erb +3 -0
  14. data/app/views/base/show.html.erb +10 -0
  15. data/app/views/symphonia/accounts/register.html.erb +25 -15
  16. data/config/locales/cs.yml +1 -1
  17. data/lib/symphonia.rb +4 -3
  18. data/lib/symphonia/base_controller.rb +39 -8
  19. data/lib/symphonia/controller_extensions.rb +2 -0
  20. data/lib/symphonia/engine.rb +9 -8
  21. data/lib/symphonia/entity_decorator.rb +34 -0
  22. data/lib/symphonia/model_attributes/attribute.rb +51 -4
  23. data/lib/symphonia/query.rb +9 -8
  24. data/lib/symphonia/user_management.rb +2 -1
  25. data/lib/symphonia/version.rb +1 -1
  26. data/spec/controllers/base_controller_spec.rb +42 -0
  27. data/spec/controllers/users_controller_spec.rb +6 -5
  28. data/spec/helpers/symphonia/entity_decorator_spec.rb +9 -0
  29. data/spec/models/query/symphonia_query_spec.rb +21 -1
  30. data/spec/models/user_spec.rb +2 -2
  31. data/spec/support/shared_controllers.rb +2 -2
  32. data/spec/support/shared_requests.rb +32 -0
  33. data/spec/support/stub_users.rb +2 -2
  34. metadata +52 -53
  35. data/app/views/symphonia/base/index.html.erb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dbaab70557fe0b832f613459ec8b05d74de1e150cd1f1976de5230ace666f0fd
4
- data.tar.gz: aae5ec3a1707998fe75f595851f5a3addbbd7daff1901f6190662a9342391e2c
3
+ metadata.gz: c5b28e0e3450123e448544ebc31cc508547f46edf4720ae1ccd14388d43f4d79
4
+ data.tar.gz: 50220dbb88357b44759b56922ed45fbdb39d318abb6984d014b4b54d28ccbbe4
5
5
  SHA512:
6
- metadata.gz: 15fde87f3e9a1748826b980e48dbcd18e7302e19db5abb52ba73c58f58a760b5e0aec33ad9d2caeb58af6eb869a7e8bae82e46e666f6213f7b3cd286d369dc38
7
- data.tar.gz: 37913e513d2d135311daafd33fa5d1beea5ed01da83d002f4742e95425a74bb8aeff4c62280c8d4333f7612236b2b5fdee11007dae3710b34d4208c7c1d2538d
6
+ metadata.gz: b3d488537c8872ce378ea9cb196b01f5cf0f5a116fa2b849e6e7d20cf5c4e4f56c5e69eae370c74885a752e837a58ecb7899649b0e47fa8c445510a8f806bf82
7
+ data.tar.gz: fb4e0f340bd7efa71dbca9a549151c01ffda76147282f2257dc0ba1fe19368880b442db5d810e538931c7a47e30ada443834e22f743dbbe6f5d5a85dcd13dff9
@@ -1,8 +1,14 @@
1
+ #require:
2
+ # - rubocop-rails
1
3
  All:
2
4
  Rails: true
3
5
  AllCops:
4
6
  TargetRubyVersion: 2.5
5
7
 
8
+ Layout/EmptyLinesAroundClassBody:
9
+ EnforcedStyle: empty_lines_special
10
+ Layout/EmptyLinesAroundModuleBody:
11
+ EnforcedStyle: empty_lines_except_namespace
6
12
  Layout/MultilineMethodCallIndentation:
7
13
  EnforcedStyle: indented_relative_to_receiver
8
14
 
@@ -0,0 +1,5 @@
1
+ //= link_tree ../images
2
+ // link_directory ../javascripts/symphonia .js
3
+ // link_directory ../stylesheets/symphonia .css
4
+ //= link ../../javascripts/symphonia/application.js
5
+ //= link ../../stylesheets/symphonia/application.css
@@ -0,0 +1,4 @@
1
+ # @abstract used for templates
2
+ class BaseController < ApplicationController
3
+ include Symphonia::BaseController
4
+ end
@@ -23,17 +23,17 @@ module Symphonia
23
23
  def create
24
24
  menu_item(:register)
25
25
  @user.attributes = user_params
26
- if Symphonia.config[:self_activation_enabled]
27
- @user.status = @user.class.statuses[:active]
28
- else
29
- @user.status = @user.class.statuses[:pending]
30
- end
26
+ @user.status = if Symphonia.config[:self_activation_enabled]
27
+ @user.class.statuses[:active]
28
+ else
29
+ @user.class.statuses[:pending]
30
+ end
31
31
  respond_to do |format|
32
32
  verified = if defined?(Recaptcha)
33
- @user.valid? && verify_recaptcha(model: @user)
34
- else
35
- true
36
- end
33
+ @user.valid? && verify_recaptcha(model: @user)
34
+ else
35
+ true
36
+ end
37
37
  if verified && @user.save
38
38
  Notifier.activation_user(@user).deliver_now
39
39
  Notifier.user_registered(@user).deliver_now
@@ -113,7 +113,7 @@ module Symphonia
113
113
  @user = find_account_by_token(params.require(:id))
114
114
  return render_404 if @user.nil?
115
115
 
116
- if params[:password]# && params[:password_confirmation]
116
+ if params[:password] # && params[:password_confirmation]
117
117
  @user.password = params[:password]
118
118
  # @user.password_confirmation = params[:password_confirmation]
119
119
  end
@@ -145,11 +145,12 @@ module Symphonia
145
145
 
146
146
  def prepare_user
147
147
  return render_403 unless Symphonia.config[:allow_registrations]
148
+
148
149
  @user = User.new
149
150
  end
150
151
 
151
152
  def user_params
152
- params.require(:user).permit(:login, :first_name, :last_name, :password, :password_confirmation, :email, :mail, preference_ids: [])
153
+ params.require(:user).permit(:login, :name, :first_name, :last_name, :password, :password_confirmation, :email, :mail, preference_ids: [])
153
154
  end
154
155
 
155
156
  def current_account
@@ -1,6 +1,6 @@
1
1
  module Symphonia
2
2
  class UsersController < ApplicationController
3
- include Swagger::Blocks
3
+ include ::Swagger::Blocks
4
4
 
5
5
  swagger_path '/admin/users/{id}.json' do
6
6
  operation :get do
@@ -165,4 +165,4 @@ module Symphonia
165
165
  params.require(:user).permit(allowed)
166
166
  end
167
167
  end
168
- end
168
+ end
@@ -69,8 +69,7 @@ module Symphonia
69
69
  options_class = options.delete(:class)
70
70
  css_class = is_current_column ? "current #{current_column.direction} #{options_class}" : options_class
71
71
  direction = is_current_column && current_column.direction == 'asc' ? 'desc' : 'asc'
72
- sort_params = { "#{prefix}sort" => column.sort_definition.column,
73
- "#{prefix}direction" => direction,
72
+ sort_params = { "#{prefix}sort" => "#{column.sort_definition.column}:#{direction}",
74
73
  "#{prefix}page" => nil }
75
74
  @_c.link_to title, query.to_params.merge(sort_params), options.merge({ class: css_class })
76
75
  end
@@ -99,6 +99,7 @@ module Symphonia
99
99
  # def form_path
100
100
  # 'symphonia/users/form'
101
101
  # end
102
+
102
103
  private
103
104
 
104
105
  def require_password?
@@ -0,0 +1,15 @@
1
+ <%= symphonia_form_for(@entity) do |f| %>
2
+ <%= f.error_messages %>
3
+
4
+ <% @entity.class.registered_attributes.each do |name, attribute| %>
5
+ <% next unless attribute.input_field %>
6
+ <p>
7
+ <%= f.send attribute.input_field, name, attribute.input_options %>
8
+ </p>
9
+ <% end %>
10
+
11
+ <p class="buttons">
12
+ <%= link_to_back(polymorphic_path(@entity.class)) %>
13
+ <%= f.primary %>
14
+ </p>
15
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <%= title @entity.to_s %>
2
+
3
+ <%= render 'form' %>
@@ -0,0 +1,5 @@
1
+ <%= title :"label_#{controller.model_name.to_s.pluralize}" do %>
2
+ <%= link_to_new_entity %>
3
+ <% end %>
4
+ <%= render('symphonia/common/filters', remote: true) %>
5
+ <%= render_symphonia_table(@query) %>
@@ -0,0 +1,3 @@
1
+ <%= title t("label_#{controller.model_name}_new") %>
2
+
3
+ <%= render 'form' %>
@@ -0,0 +1,10 @@
1
+ <%= title @entity.to_s do %>
2
+ <%= link_to icon("edit", t(:button_edit)), edit_polymorphic_path(@entity) %>
3
+ <% end %>
4
+
5
+ <% @entity.attributes do |name, value, attribute| %>
6
+ <div class="<%= attribute.class.name.demodulize.underscore %>">
7
+ <dt><%= @entity.label name %></dt>
8
+ <dd><%= value %></dd>
9
+ </div>
10
+ <% end %>
@@ -1,20 +1,30 @@
1
1
  <% name = @user.class.name.demodulize.downcase %>
2
2
  <%= title(t(:"label_register_new_#{name}")) %>
3
- <%= symphonia_form_for(@user, url: account_register_path) do |f| %>
4
- <div style="width:1px;height: 1px;visibility: hidden"><%= check_box_tag :terms, true %></div>
5
3
 
6
- <%= render(partial: "symphonia/#{name.pluralize}/form", locals: { f: f }) %>
7
-
8
- <% if defined? Recaptcha %>
9
- <fieldset>
10
- <%= content_tag(:legend, t(:text_explanation_recaptcha)) %>
11
- <div class="form-group">
12
- <div class="col-sm-offset-4 col-sm-5">
13
- <%#= invisible_recaptcha_tags %>
14
- <%= recaptcha_tags(:display => {:theme => 'white'}) %>
4
+ <div class="row">
5
+ <div class="col-md-6 col-xs-12 mx-auto">
6
+ <div class="card w-75 mx-auto">
7
+ <div class="card-body">
8
+ <%= symphonia_form_for(@user, url: account_register_path) do |f| %>
9
+ <div style="width:1px;height: 1px;visibility: hidden"><%= check_box_tag :terms, true %></div>
10
+ <%= f.error_messages %>
11
+ <%= f.email_field :mail, required: true, prepend: "@" %>
12
+ <%= f.text_field :name, required: true, prepend: icon("user") %>
13
+ <%= f.password_field :password, required: true, prepend: icon('key') %>
14
+ <% if defined? Recaptcha %>
15
+ <fieldset>
16
+ <%= content_tag(:legend, t(:text_explanation_recaptcha)) %>
17
+ <div class="form-group">
18
+ <div class="col-sm-offset-4 col-sm-5">
19
+ <%#= invisible_recaptcha_tags %>
20
+ <%= recaptcha_tags(:display => { :theme => 'white' }) %>
21
+ </div>
22
+ </div>
23
+ </fieldset>
24
+ <% end %>
25
+ <%= f.primary t(:button_register), class: 'btn btn-primary btn-block' %>
26
+ <% end %>
15
27
  </div>
16
28
  </div>
17
- </fieldset>
18
- <% end %>
19
- <%= f.primary t(:button_register) %>
20
- <% end %>
29
+ </div>
30
+ </div>
@@ -14,7 +14,7 @@ cs:
14
14
  # not_confirmed: Your account is not confirmed
15
15
  # not_approved: Your account is not approved
16
16
  # no_authentication_details: You did not provide any details for authentication.
17
- general_credentials_error: login nebo heslo
17
+ general_credentials_error: Login nebo heslo není správně
18
18
  models:
19
19
  user_session: Přihlášení
20
20
  attributes:
@@ -2,14 +2,15 @@
2
2
  module Symphonia
3
3
  include ::ActiveSupport::Configurable
4
4
 
5
+ autoload :Attachable, 'symphonia/attachable'
5
6
  autoload :BaseController, 'symphonia/base_controller'
7
+ autoload :BootstrapLinkRender, 'symphonia/bootstrap_link_render'
6
8
  autoload :ControllerExtensions, 'symphonia/controller_extensions'
9
+ autoload :EntityDecorator, 'symphonia/entity_decorator'
7
10
  autoload :FormBuilder, 'symphonia/form_builder'
8
- autoload :BootstrapLinkRender, 'symphonia/bootstrap_link_render'
9
- autoload :Query, 'symphonia/query'
10
11
  autoload :ModelAttributes, 'symphonia/model_attributes'
11
12
  autoload :ModelFilters, 'symphonia/model_filters'
12
- autoload :Attachable, 'symphonia/attachable'
13
+ autoload :Query, 'symphonia/query'
13
14
  autoload :QueryColumns, 'symphonia/query_columns'
14
15
 
15
16
  module ActionCable
@@ -1,4 +1,11 @@
1
1
  module Symphonia
2
+ # General controller for CRUD operations of Entity
3
+ #
4
+ # How to use:
5
+ # include Symphonia::BaseController
6
+ # def model
7
+ # YourModel
8
+ # end
2
9
  module BaseController
3
10
  extend ActiveSupport::Concern
4
11
 
@@ -9,8 +16,30 @@ module Symphonia
9
16
  include Rails::Pagination
10
17
  helper Symphonia::RendererHelper
11
18
 
19
+ class_attribute :model
20
+
21
+ end
22
+
23
+ class_methods do
24
+
25
+ # def model=(klass)
26
+ # @model = klass
27
+ # end
28
+ #
29
+ # def model
30
+ # @model
31
+ # end
12
32
  end
13
33
 
34
+ # def model
35
+ # self.class.model
36
+ # end
37
+ # @abstract model
38
+ # by default it guess from class name of controller
39
+ # def model
40
+ # @model ||= self.class.name.remove("Controller").classify.constantize
41
+ # end
42
+
14
43
  def index
15
44
  @query ||= model.query.new
16
45
  @query.from_params params
@@ -28,7 +57,7 @@ module Symphonia
28
57
 
29
58
  def show
30
59
  respond_to do |format|
31
- format.html
60
+ format.html { @entity = Symphonia::EntityDecorator.new(@entity, view_context) }
32
61
  format.json { render json: @entity }
33
62
  end
34
63
  end
@@ -70,13 +99,18 @@ module Symphonia
70
99
  def destroy
71
100
  @entity.destroy
72
101
  respond_to do |format|
73
- format.html { redirect_back_or_default(action: :index, notice: t(:text_destroyed)) }
102
+ format.html { redirect_back_or_default(polymorphic_path(model), notice: t(:text_destroyed)) }
74
103
  format.json { head :no_content }
75
- format.js { render js: "Symphonia.filters.removeRow('#{view_context.dom_id(@entity)}')"}
104
+ format.js { render js: "Symphonia.filters.removeRow('#{view_context.dom_id(@entity)}')" }
76
105
  end
77
106
  end
78
107
 
108
+ def model_name
109
+ model.name.demodulize.underscore.to_sym
110
+ end
111
+
79
112
  private
113
+
80
114
  # Use callbacks to share common setup or constraints between actions.
81
115
  def find_entity
82
116
  @entity ||= instance_variable_set(:"@#{model_name}", model.find(params[:id]))
@@ -85,15 +119,12 @@ module Symphonia
85
119
  def safe_attributes
86
120
  []
87
121
  end
122
+
88
123
  # Never trust parameters from the scary internet, only allow the white list through.
89
124
  def entity_params
90
125
  params.require(model_name).permit(safe_attributes)
91
126
  end
92
127
 
93
- def model_name
94
- model.name.demodulize.underscore.to_sym
95
- end
96
-
97
128
  def after_create
98
129
 
99
130
  end
@@ -103,4 +134,4 @@ module Symphonia
103
134
  end
104
135
 
105
136
  end
106
- end
137
+ end
@@ -13,6 +13,8 @@ module Symphonia
13
13
 
14
14
  # force_ssl if: -> {Rails.env.production? && User.current.ssl?}
15
15
 
16
+ add_flash_types :notice
17
+ add_flash_types :info
16
18
  add_flash_types :warning
17
19
  add_flash_types :error
18
20
 
@@ -21,7 +21,7 @@ require 'acts_as_list'
21
21
  require 'bootstrap_form'
22
22
  require 'the_sortable_tree'
23
23
  require 'bootstrap-datepicker-rails'
24
- require 'wicked_pdf'
24
+ # require 'wicked_pdf'
25
25
  require 'swagger/blocks'
26
26
 
27
27
  module Symphonia
@@ -82,6 +82,7 @@ module Symphonia
82
82
  end
83
83
 
84
84
  initializer :assets do |_app|
85
+ config.assets.precompile << 'symphonia/application.css'
85
86
  if defined?(::Ckeditor)
86
87
  config.assets.precompile << 'ckeditor/**/*'
87
88
  config.assets.precompile << 'symphonia/symphonia_ckeditor.js'
@@ -96,13 +97,13 @@ module Symphonia
96
97
 
97
98
  end
98
99
 
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
100
+ # initializer :wicked_pdf do |_app|
101
+ # WickedPdf.config = {
102
+ # layout: 'application.pdf',
103
+ # print_media_type: true,
104
+ # viewport_size: '1280x800', zoom: 0.7, dpi: 300
105
+ # }
106
+ # end
106
107
 
107
108
  initializer :api_paginate do
108
109
  ApiPagination.configure do |config|
@@ -0,0 +1,34 @@
1
+ module Symphonia
2
+ # This class decorate general entity
3
+ class EntityDecorator < SimpleDelegator
4
+
5
+ def initialize(entity, view_context)
6
+ @view_context = view_context
7
+ super(entity)
8
+ end
9
+
10
+ def registered_attributes
11
+ __getobj__.class.registered_attributes
12
+ end
13
+
14
+ def label(name, **options)
15
+ __getobj__.class.human_attribute_name name, options
16
+ end
17
+
18
+ def attributes(&block)
19
+ registered_attributes.collect do |name, attr|
20
+ value = __getobj__.format_value(name, @view_context)
21
+ yield name, value, attr if block_given?
22
+ [name, value]
23
+ end.to_h
24
+ end
25
+
26
+ # def name
27
+ # @name ||= super || registered_attributes.find { |name, a| name == :name }.last
28
+ # end
29
+ #
30
+ # def title
31
+ # super || name || to_s
32
+ # end
33
+ end
34
+ end
@@ -22,7 +22,7 @@ module Symphonia
22
22
  entity.send(name)
23
23
  end
24
24
 
25
- def format(view, entity, options={})
25
+ def format(view, entity, options = {})
26
26
  @format_options = options
27
27
  if @formatter.is_a?(Proc)
28
28
  @formatter.call(view, self, entity).to_s
@@ -61,6 +61,18 @@ module Symphonia
61
61
  !!@options[:default]
62
62
  end
63
63
 
64
+ def required?
65
+
66
+ end
67
+
68
+ def input_field
69
+ :text_field
70
+ end
71
+
72
+ def input_options
73
+ {}
74
+ end
75
+
64
76
  private
65
77
 
66
78
  def format_value(_view, value, _entity)
@@ -69,6 +81,15 @@ module Symphonia
69
81
  end
70
82
 
71
83
 
84
+ class TextAttribute < Attribute
85
+ def format_value(view, value, entity)
86
+ view.format_text(value)
87
+ end
88
+
89
+ def input_field
90
+ :text_area
91
+ end
92
+ end
72
93
  class DecimalAttribute < Attribute
73
94
  def format_value(view, value, entity)
74
95
  view.format_price(value)
@@ -80,6 +101,14 @@ module Symphonia
80
101
  def format_value(view, value, entity)
81
102
  view.t("#{@klass.name.underscore}.#{name.to_s.pluralize}.#{value}", format_options)
82
103
  end
104
+
105
+ def input_field
106
+ :select
107
+ end
108
+
109
+ def input_options
110
+ []
111
+ end
83
112
  end
84
113
 
85
114
  class LinkAttribute < Attribute
@@ -101,12 +130,26 @@ module Symphonia
101
130
  end
102
131
 
103
132
  def title
104
- @klass.human_attribute_name(@klass.reflect_on_association(name).foreign_key, @options[:i18n] || {})
133
+ if (ref = @klass.reflect_on_association(name)).macro == :belongs_to
134
+ @klass.human_attribute_name(ref.foreign_key, @options[:i18n] || {})
135
+ else
136
+ super
137
+ end
138
+
105
139
  end
106
140
 
107
141
  def format_value(view, value, entity)
108
- view.link_to value.to_s, value, format_options
142
+ if value.is_a?(ActiveRecord::Associations::CollectionProxy) || value.is_a?(Array)
143
+ value.collect { |v| view.link_to v.to_s, v, format_options }.join("\n").html_safe
144
+ else
145
+ view.link_to value.to_s, value, format_options
146
+ end
147
+ end
148
+
149
+ def input_field
150
+ nil
109
151
  end
152
+
110
153
  end
111
154
 
112
155
  class BooleanAttribute < Attribute
@@ -117,6 +160,10 @@ module Symphonia
117
160
  view.icon('false', view.t(:false))
118
161
  end
119
162
  end
163
+
164
+ def input_field
165
+ :check_box
166
+ end
120
167
  end
121
168
 
122
169
  class DateAttribute < Attribute
@@ -134,4 +181,4 @@ module Symphonia
134
181
  # alias
135
182
  end
136
183
  end
137
- end
184
+ end
@@ -23,9 +23,7 @@ module Symphonia
23
23
  # @query.from_params params
24
24
  #
25
25
  end
26
- if options[:default_order]
27
- ActiveSupport::Deprecation.warn("default_order is deprecated, use just `sort`")
28
- end
26
+ ActiveSupport::Deprecation.warn("default_order is deprecated, use just `sort`") if options[:default_order]
29
27
  @active_filters = {}
30
28
  @default_sort = sort
31
29
  @default_filters = filters
@@ -33,13 +31,15 @@ module Symphonia
33
31
  @options = options
34
32
  end
35
33
 
34
+ # @param [Hash] params
35
+ # @option params [String] :sort name of column, also can be name:direction
36
+ # @option params [String] :direction ASC or DESC
37
+ # @option params [Boolean] :set_filter if `true` apply filters
36
38
  def from_params(params)
37
- @sort_col = params[:sort]
38
- @sort_dir = params[:direction]
39
+ @sort_col, @sort_dir = params[:sort]&.split(":")
40
+ @sort_dir ||= params[:direction]
39
41
  self.entity_scope = entity.like(@q) if (@q = params[:q].presence)
40
- if (@set_filter = params[:set_filter].to_boolean)
41
- setup_filters(params)
42
- end
42
+ setup_filters(params) if (@set_filter = params[:set_filter].to_boolean)
43
43
  setup_columns(params)
44
44
  end
45
45
 
@@ -255,6 +255,7 @@ module Symphonia
255
255
  def add_boolean_column(name, options = {})
256
256
  add_column(:boolean, name, options)
257
257
  end
258
+
258
259
  #
259
260
  def add_attribute_column(attribute, options = {})
260
261
  @available_columns[attribute.name] = ::Symphonia::QueryColumns::AttributeColumn.new(attribute, self, options)
@@ -12,7 +12,8 @@ module Symphonia
12
12
  # validates :mail, uniqueness: true, format: { with: Authlogic::Regex::EMAIL_NONASCII }
13
13
  # validates :password, presence: true, if: ->(u){ u.new_record? }
14
14
 
15
- validates :login, :mail, :first_name, :last_name, presence: true
15
+ validates :email, presence: true, uniqueness: { case_sensitive: false }
16
+ validates :login, :first_name, presence: true
16
17
 
17
18
  def self.current=(entity)
18
19
  Rails.logger.info("* #{entity.class.name}: #{entity.login} id: #{entity.id}") if entity
@@ -1,3 +1,3 @@
1
1
  module Symphonia
2
- VERSION = '3.0.3'
2
+ VERSION = '3.1.0'
3
3
  end
@@ -0,0 +1,42 @@
1
+ class ModelA
2
+
3
+ def self.find(_)
4
+ new
5
+ end
6
+ end
7
+
8
+ class ModelB
9
+
10
+ def self.find(_)
11
+ new
12
+ end
13
+ end
14
+
15
+ class DummyBaseA < Symphonia::ApplicationController
16
+ include Symphonia::BaseController
17
+ self.model = ModelA
18
+ end
19
+ class DummyBaseB < DummyBaseA
20
+ # include Symphonia::BaseController
21
+ self.model = ModelB
22
+ end
23
+
24
+ RSpec.describe DummyBaseB do
25
+ # subject { described_class.new }
26
+ controller do
27
+ def show
28
+ render plain: model.name
29
+ end
30
+ end
31
+ it "#model" do
32
+ subject = DummyBaseA.new
33
+ expect(subject.model).to eq ModelA
34
+ subject = DummyBaseB.new
35
+ expect(subject.model).to eq ModelB
36
+ end
37
+
38
+ it "#show" do
39
+ get :show, params: { id: 1 }
40
+ expect(response.body).to eq "ModelB"
41
+ end
42
+ end
@@ -1,4 +1,5 @@
1
- # require_relative '../spec_helper.rb'
1
+ # frozen_string_literal: true
2
+
2
3
  module Symphonia
3
4
  describe UsersController, type: 'controller' do
4
5
  routes { Symphonia::Engine.routes }
@@ -13,22 +14,22 @@ module Symphonia
13
14
 
14
15
  context 'not found' do
15
16
  it '#show' do
16
- get :show, params: {id: 0 }
17
+ get :show, params: { id: 0 }
17
18
  expect(response).to have_http_status :not_found
18
19
  end
19
20
  end
20
21
 
21
22
  it '#archive' do
22
23
  user.update_columns status: 'active'
23
- expect ( post :archive, params: { id: user } )
24
+ expect(post(:archive, params: { id: user }))
24
25
  expect(response).to redirect_to users_url
25
26
  expect(user.reload.status).to eq 'archived'
26
27
  end
27
28
 
28
29
  it '#unarchive' do
29
30
  user.update_columns status: 'archived'
30
- expect( post :unarchive, params: { id: user } )
31
- expect(ActionMailer::DeliveryJob).to have_been_enqueued
31
+ expect(post(:unarchive, params: { id: user }))
32
+ expect(ActionMailer::MailDeliveryJob).to have_been_enqueued
32
33
  expect(response).to redirect_to users_url
33
34
  expect(user.reload.status).to eq 'active'
34
35
  end
@@ -0,0 +1,9 @@
1
+ RSpec.describe Symphonia::ApplicationHelper do
2
+ let(:entity) { FactoryBot.create :user }
3
+ subject { Symphonia::EntityDecorator.new entity, spy }
4
+
5
+ it "#attributes" do
6
+ expect(subject.attributes).to be_a Hash
7
+ expect(subject.attributes[:name]).to include "<a", "mailto", entity.email
8
+ end
9
+ end
@@ -53,6 +53,26 @@ RSpec.describe Symphonia::Query do
53
53
  q.from_params(column_names: "name")
54
54
  expect(q.column_names).to match_array [:name]
55
55
  end
56
+
57
+ context "sorting" do
58
+ it "basic" do
59
+ q = DummyQueryEntity.query.new
60
+ q.from_params sort: "name"
61
+ scope = double
62
+ expect(q).to receive(:scope).and_return scope
63
+ expect(scope).to receive(:order).with include("first_name", "last_name", "ASC")
64
+ q.entities
65
+ end
66
+
67
+ it "shortcut direction" do
68
+ q = DummyQueryEntity.query.new
69
+ q.from_params sort: "name:desc"
70
+ scope = double
71
+ expect(q).to receive(:scope).and_return scope
72
+ expect(scope).to receive(:order).with include("first_name", "last_name", "DESC")
73
+ q.entities
74
+ end
75
+ end
56
76
  end
57
77
 
58
78
  describe "#entities" do
@@ -67,4 +87,4 @@ RSpec.describe Symphonia::Query do
67
87
 
68
88
  end
69
89
 
70
- end
90
+ end
@@ -20,8 +20,8 @@ RSpec.describe Symphonia::User do
20
20
  expect { FactoryBot.create(:user, password: nil) }.to raise_error ActiveRecord::RecordInvalid
21
21
  end
22
22
  it "do not require password for external_ids" do
23
- expect { FactoryBot.create(:user, password: nil, external_id: "ex1") }.not_to raise_error ActiveRecord::RecordInvalid
23
+ expect { FactoryBot.create(:user, password: nil, external_id: "ex1") }.not_to raise_error
24
24
  end
25
25
  end
26
26
 
27
- end
27
+ end
@@ -22,10 +22,10 @@ RSpec.shared_examples 'a controller actions' do |factory|
22
22
  end
23
23
 
24
24
  it '#show' do
25
- get :show, params: {id: entity, format: 'json'}
25
+ get :show, params: { id: entity, format: 'json' }
26
26
  expect(response).to have_http_status(:success)
27
27
  expect(response.body).to include "id", entity.id.to_s
28
28
  end
29
29
  end
30
30
 
31
- end
31
+ end
@@ -0,0 +1,32 @@
1
+ RSpec.shared_examples 'a requests actions' do |factory|
2
+ let(:entity) { FactoryBot.create(factory) }
3
+ let(:entities_list) { FactoryBot.create_list(factory, 3) }
4
+
5
+ it '#index' do
6
+ entities_list
7
+ # get :index, params: { use_route: 'admin' }
8
+ get polymorphic_path(factory.to_s.pluralize)
9
+ expect(response).to have_http_status(:success)
10
+ end
11
+
12
+ it '#destroy' do
13
+ entity # touch
14
+ expect { delete polymorphic_path(entity) }.to change(entity.class, :count).by(-1)
15
+ end
16
+
17
+ context 'json' do
18
+
19
+ it '#index' do
20
+ entities_list
21
+ get polymorphic_path(factory.to_s.pluralize, format: "json")
22
+ expect(response).to have_http_status(:success)
23
+ end
24
+
25
+ it '#show' do
26
+ get polymorphic_path(entity)
27
+ expect(response).to have_http_status(:success)
28
+ expect(response.body).to include "id", entity.id.to_s
29
+ end
30
+ end
31
+
32
+ end
@@ -1,9 +1,9 @@
1
1
  def admin_user
2
- @admin_user ||= FactoryBot.build_stubbed :user, :admin
2
+ @admin_user ||= FactoryBot.create :user, :admin
3
3
  end
4
4
 
5
5
  def regular_user
6
- @regular_user ||= FactoryBot.build_stubbed :user
6
+ @regular_user ||= FactoryBot.create :user
7
7
  end
8
8
 
9
9
  def add_permission *args
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: symphonia
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.3
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lukas Pokorny
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-06 00:00:00.000000000 Z
11
+ date: 2019-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -30,42 +30,42 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '5.2'
33
+ version: '6.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '5.2'
40
+ version: '6.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rails-i18n
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '5'
47
+ version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '5'
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: turbolinks
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '5'
61
+ version: '0'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '5'
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: authlogic
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 4.1.3
89
+ version: '4.1'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 4.1.3
96
+ version: '4.1'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: will_paginate
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -240,14 +240,14 @@ dependencies:
240
240
  requirements:
241
241
  - - "~>"
242
242
  - !ruby/object:Gem::Version
243
- version: '4.1'
243
+ version: '4.3'
244
244
  type: :runtime
245
245
  prerelease: false
246
246
  version_requirements: !ruby/object:Gem::Requirement
247
247
  requirements:
248
248
  - - "~>"
249
249
  - !ruby/object:Gem::Version
250
- version: '4.1'
250
+ version: '4.3'
251
251
  - !ruby/object:Gem::Dependency
252
252
  name: the_sortable_tree
253
253
  requirement: !ruby/object:Gem::Requirement
@@ -276,20 +276,6 @@ dependencies:
276
276
  - - ">="
277
277
  - !ruby/object:Gem::Version
278
278
  version: '0'
279
- - !ruby/object:Gem::Dependency
280
- name: wicked_pdf
281
- requirement: !ruby/object:Gem::Requirement
282
- requirements:
283
- - - ">="
284
- - !ruby/object:Gem::Version
285
- version: '0'
286
- type: :runtime
287
- prerelease: false
288
- version_requirements: !ruby/object:Gem::Requirement
289
- requirements:
290
- - - ">="
291
- - !ruby/object:Gem::Version
292
- version: '0'
293
279
  - !ruby/object:Gem::Dependency
294
280
  name: sidekiq
295
281
  requirement: !ruby/object:Gem::Requirement
@@ -338,14 +324,14 @@ dependencies:
338
324
  requirements:
339
325
  - - "~>"
340
326
  - !ruby/object:Gem::Version
341
- version: '3.8'
327
+ version: 4.0.0.beta
342
328
  type: :runtime
343
329
  prerelease: false
344
330
  version_requirements: !ruby/object:Gem::Requirement
345
331
  requirements:
346
332
  - - "~>"
347
333
  - !ruby/object:Gem::Version
348
- version: '3.8'
334
+ version: 4.0.0.beta
349
335
  - !ruby/object:Gem::Dependency
350
336
  name: factory_bot_rails
351
337
  requirement: !ruby/object:Gem::Requirement
@@ -364,72 +350,72 @@ dependencies:
364
350
  name: database_cleaner
365
351
  requirement: !ruby/object:Gem::Requirement
366
352
  requirements:
367
- - - "~>"
353
+ - - ">="
368
354
  - !ruby/object:Gem::Version
369
- version: '1.7'
355
+ version: '0'
370
356
  type: :runtime
371
357
  prerelease: false
372
358
  version_requirements: !ruby/object:Gem::Requirement
373
359
  requirements:
374
- - - "~>"
360
+ - - ">="
375
361
  - !ruby/object:Gem::Version
376
- version: '1.7'
362
+ version: '0'
377
363
  - !ruby/object:Gem::Dependency
378
364
  name: faker
379
365
  requirement: !ruby/object:Gem::Requirement
380
366
  requirements:
381
- - - "~>"
367
+ - - ">="
382
368
  - !ruby/object:Gem::Version
383
- version: '1.8'
369
+ version: '0'
384
370
  type: :runtime
385
371
  prerelease: false
386
372
  version_requirements: !ruby/object:Gem::Requirement
387
373
  requirements:
388
- - - "~>"
374
+ - - ">="
389
375
  - !ruby/object:Gem::Version
390
- version: '1.8'
376
+ version: '0'
391
377
  - !ruby/object:Gem::Dependency
392
378
  name: pry-rails
393
379
  requirement: !ruby/object:Gem::Requirement
394
380
  requirements:
395
- - - "~>"
381
+ - - ">="
396
382
  - !ruby/object:Gem::Version
397
- version: '0.3'
383
+ version: '0'
398
384
  type: :runtime
399
385
  prerelease: false
400
386
  version_requirements: !ruby/object:Gem::Requirement
401
387
  requirements:
402
- - - "~>"
388
+ - - ">="
403
389
  - !ruby/object:Gem::Version
404
- version: '0.3'
390
+ version: '0'
405
391
  - !ruby/object:Gem::Dependency
406
392
  name: sqlite3
407
393
  requirement: !ruby/object:Gem::Requirement
408
394
  requirements:
409
395
  - - "~>"
410
396
  - !ruby/object:Gem::Version
411
- version: 1.3.6
397
+ version: '1.3'
412
398
  type: :runtime
413
399
  prerelease: false
414
400
  version_requirements: !ruby/object:Gem::Requirement
415
401
  requirements:
416
402
  - - "~>"
417
403
  - !ruby/object:Gem::Version
418
- version: 1.3.6
404
+ version: '1.3'
419
405
  - !ruby/object:Gem::Dependency
420
406
  name: sass-rails
421
407
  requirement: !ruby/object:Gem::Requirement
422
408
  requirements:
423
- - - "~>"
409
+ - - ">="
424
410
  - !ruby/object:Gem::Version
425
- version: '5.0'
411
+ version: '0'
426
412
  type: :runtime
427
413
  prerelease: false
428
414
  version_requirements: !ruby/object:Gem::Requirement
429
415
  requirements:
430
- - - "~>"
416
+ - - ">="
431
417
  - !ruby/object:Gem::Version
432
- version: '5.0'
418
+ version: '0'
433
419
  description: Basis of my applications
434
420
  email:
435
421
  - luk4s.pokorny@gmail.com
@@ -441,6 +427,7 @@ files:
441
427
  - LICENSE
442
428
  - README.md
443
429
  - Rakefile
430
+ - app/assets/config/symphonia_manifest.js
444
431
  - app/assets/images/bg-checker.png
445
432
  - app/assets/images/bullet.gif
446
433
  - app/assets/images/close.png
@@ -453,7 +440,7 @@ files:
453
440
  - app/assets/javascripts/ckeditor/plugins/image_chooser/plugin.js
454
441
  - app/assets/javascripts/symphonia/Sortable.js
455
442
  - app/assets/javascripts/symphonia/_core.js
456
- - app/assets/javascripts/symphonia/application.js.erb
443
+ - app/assets/javascripts/symphonia/application.js
457
444
  - app/assets/javascripts/symphonia/filters.js
458
445
  - app/assets/javascripts/symphonia/symphonia_bootstrap_dialog.js
459
446
  - app/assets/javascripts/symphonia/symphonia_ckeditor.js
@@ -462,6 +449,7 @@ files:
462
449
  - app/assets/stylesheets/symphonia/filters.scss
463
450
  - app/assets/stylesheets/symphonia/symphonia_bootstrap.scss
464
451
  - app/channels/application_cable/channel.rb
452
+ - app/controllers/base_controller.rb
465
453
  - app/controllers/symphonia/accounts_controller.rb
466
454
  - app/controllers/symphonia/admin_controller.rb
467
455
  - app/controllers/symphonia/api_controller.rb
@@ -491,6 +479,11 @@ files:
491
479
  - app/models/symphonia/swagger/responses.rb
492
480
  - app/models/symphonia/user.rb
493
481
  - app/models/symphonia/user_session.rb
482
+ - app/views/base/_form.html.erb
483
+ - app/views/base/edit.html.erb
484
+ - app/views/base/index.html.erb
485
+ - app/views/base/new.html.erb
486
+ - app/views/base/show.html.erb
494
487
  - app/views/common/403.html.erb
495
488
  - app/views/common/404.html.erb
496
489
  - app/views/layouts/symphonia/_modal.html.erb
@@ -511,7 +504,6 @@ files:
511
504
  - app/views/symphonia/accounts/update.js.erb
512
505
  - app/views/symphonia/admin/index.html.erb
513
506
  - app/views/symphonia/attachments/destroy.js.erb
514
- - app/views/symphonia/base/index.html.erb
515
507
  - app/views/symphonia/common/_editable_images_grid.html.erb
516
508
  - app/views/symphonia/common/_filters.html.erb
517
509
  - app/views/symphonia/common/_locale_chooser.html.erb
@@ -573,6 +565,7 @@ files:
573
565
  - lib/symphonia/bootstrap_link_render.rb
574
566
  - lib/symphonia/controller_extensions.rb
575
567
  - lib/symphonia/engine.rb
568
+ - lib/symphonia/entity_decorator.rb
576
569
  - lib/symphonia/form_builder.rb
577
570
  - lib/symphonia/menu_manager.rb
578
571
  - lib/symphonia/model_attributes.rb
@@ -596,6 +589,7 @@ files:
596
589
  - spec/controllers/account_controller_spec.rb
597
590
  - spec/controllers/admin_controller_spec.rb
598
591
  - spec/controllers/api_controller_spec.rb
592
+ - spec/controllers/base_controller_spec.rb
599
593
  - spec/controllers/filters_controller_spec.rb
600
594
  - spec/controllers/images_controller_spec.rb
601
595
  - spec/controllers/login_controller_spec.rb
@@ -603,6 +597,7 @@ files:
603
597
  - spec/controllers/users_controller_spec.rb
604
598
  - spec/factories/factories.rb
605
599
  - spec/helpers/symphonia/application_helper_spec.rb
600
+ - spec/helpers/symphonia/entity_decorator_spec.rb
606
601
  - spec/helpers/symphonia/renderer_helper_spec.rb
607
602
  - spec/mailers/previews/symphonia/notifier_preview.rb
608
603
  - spec/mailers/symphonia/notifier_spec.rb
@@ -623,6 +618,7 @@ files:
623
618
  - spec/support/query.rb
624
619
  - spec/support/shared.rb
625
620
  - spec/support/shared_controllers.rb
621
+ - spec/support/shared_requests.rb
626
622
  - spec/support/stub_users.rb
627
623
  - spec/support/symphonia.jpg
628
624
  - spec/support/wait_for_ajax.rb
@@ -647,7 +643,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
647
643
  - !ruby/object:Gem::Version
648
644
  version: '0'
649
645
  requirements: []
650
- rubygems_version: 3.0.4
646
+ rubygems_version: 3.0.6
651
647
  signing_key:
652
648
  specification_version: 4
653
649
  summary: My administration
@@ -673,6 +669,7 @@ test_files:
673
669
  - spec/support/shared.rb
674
670
  - spec/support/wait_for_ajax.rb
675
671
  - spec/support/shared_controllers.rb
672
+ - spec/support/shared_requests.rb
676
673
  - spec/support/query.rb
677
674
  - spec/factories/factories.rb
678
675
  - spec/controllers/roles_controller_spec.rb
@@ -682,8 +679,10 @@ test_files:
682
679
  - spec/controllers/filters_controller_spec.rb
683
680
  - spec/controllers/admin_controller_spec.rb
684
681
  - spec/controllers/account_controller_spec.rb
682
+ - spec/controllers/base_controller_spec.rb
685
683
  - spec/controllers/images_controller_spec.rb
686
684
  - spec/views/filters/options.html.erb_spec.rb
687
685
  - spec/rails_helper.rb
688
686
  - spec/helpers/symphonia/application_helper_spec.rb
689
687
  - spec/helpers/symphonia/renderer_helper_spec.rb
688
+ - spec/helpers/symphonia/entity_decorator_spec.rb
@@ -1,5 +0,0 @@
1
- <%= title :"label_#{controller.model.name.underscore}" do %>
2
- <%= link_to_new_entity %>
3
- <% end %>
4
- <%= render('symphonia/common/filters', remote: true) %>
5
- <%= render_symphonia_table(@query) %>