symphonia 3.0.3 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
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) %>