five-two-nw-olivander 0.1.2.17 → 0.1.2.18

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 60ef0e4f6cf44268d5836df99ce2f7548b77f6494a1de083ec0374c58c5f823c
4
- data.tar.gz: 56d4c32092f2fd4dbeca7f8470fb26f01a23b0a3f2f38e10a734119a745a39c3
3
+ metadata.gz: 8a36c828d7544eb3e49f262fb2535f738a51e1c12d190eab8faad0d23628fe28
4
+ data.tar.gz: 3c92c632d2a9684280afbc700b5fa2984b85998c24c2856babeaeba77dfe4ee8
5
5
  SHA512:
6
- metadata.gz: b58d17599c9bff68932f749af403b809bd7080a7e77fb9dacb943e5f5558e26010ea0cea38e461fa11abaf4847c3bdd81de376622c96c83b32e72df2208418d2
7
- data.tar.gz: d2345d025f1460ea4c3a2c7b806885eb514cda39e284400e773da772ac68ebc64596d11841b5a11ae393ffdd3ea5d041e5bc5d580bff50eb79ec5003118167fa
6
+ metadata.gz: eab8679d522df001fb3d21274571af6da60ed1d825b1d5f2b9fbe7e0f13f7c9c48ff7b81a7bc19d77464088ad5c962e91e6d8e51343e72cdd2aba7f78460eb0d
7
+ data.tar.gz: 95283a4df656bb868b541131a1fe21aa2ba16eac4cf38280a6df61666b81f6c728015aadd0df4802c5125d046b2de246a7bdd03740bee84ae44a3f92037c1eb5
@@ -0,0 +1,10 @@
1
+ - @resource.class.resource_field_groups.select{ |x| x.editable }.each do |rfg|
2
+ %h3= resource_field_group_label(@resource.class, rfg.key) unless rfg.key == :default
3
+ - rfg.sections.each do |section|
4
+ .row
5
+ - section.fields.each do |field|
6
+ %div{ class: section.column_class }
7
+ - if field.type == :association
8
+ = @f.association field.sym, disabled: !field.editable
9
+ - else
10
+ = @f.input field.sym, disabled: !field.editable
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Olivander::Components::ResourceFormComponent < ViewComponent::Base
4
+ delegate :resource_field_group_label, to: :helpers
5
+
6
+ def initialize(resource, form_builder)
7
+ @resource = resource
8
+ @f = form_builder
9
+ super
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ - @resource.class.resource_field_groups.each do |rfg|
2
+ %h3= resource_field_group_label(@resource.class, rfg.key) unless rfg.key == :default
3
+ %table.table.table-hover.table-striped
4
+ %thead
5
+ %tr
6
+ - 12.times do
7
+ %td{ style: 'width: 8.33%; height: 0px' }
8
+ %tbody
9
+ - rfg.sections.each do |section|
10
+ - section.fields.each_slice(section.columns) do |slice|
11
+ - colspan = (12 - slice.size) / section.columns
12
+ %tr
13
+ - slice.each do |f|
14
+ %th.text-right{ style: 'width: 10%' }= field_label_for(@resource.class, f.sym)
15
+ - max_columns = rfg.max_section_columns
16
+ %td{ colspan: colspan }
17
+ - val = @resource.send(f.sym)
18
+ - case f.type
19
+ - when :string
20
+ = val
21
+ - when :boolean
22
+ - icon_class = val ? 'fa-check text-success' : 'fa-times text-danger'
23
+ %i.fa{ class: icon_class }
24
+ - when :association
25
+ = link_to val if val.present?
26
+ - else
27
+ = val
28
+ - (section.columns-slice.size).times do
29
+ %th
30
+ %td{ colspan: colspan }
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Olivander::Components::ResourceShowComponent < ViewComponent::Base
4
+ delegate :field_label_for, to: :helpers
5
+ delegate :resource_field_group_label, to: :helpers
6
+
7
+ def initialize(resource, actions)
8
+ @resource = resource
9
+ @actions = actions
10
+ super
11
+ end
12
+ end
@@ -7,6 +7,132 @@ module Olivander
7
7
  def auto_form_attributes
8
8
  attributes.keys - ['updated_at', 'created_at', 'deleted_at']
9
9
  end
10
+
11
+ def self.method_missing(m, *args, &block)
12
+ if %i[auto_resource_fields resource_field_groups resource_field_group].include?(m)
13
+ include(Olivander::Resources::ResourceFields)
14
+ send(m, *args, &block)
15
+ else
16
+ super
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ module ResourceFields
23
+ extend ActiveSupport::Concern
24
+ SKIPPED_ATTRIBUTES = %i[id created_at updated_at deleted_at]
25
+
26
+ included do
27
+ cattr_accessor :current_resource_field_group
28
+ cattr_accessor :current_resource_field_row
29
+ cattr_accessor :resource_field_group_collection
30
+
31
+ def self.resource_field_groups
32
+ auto_resource_fields if self.resource_field_group_collection.nil?
33
+ self.resource_field_group_collection
34
+ end
35
+
36
+ def self.auto_resource_fields(columns: 2, only: [])
37
+ if current_resource_field_group.nil?
38
+ resource_field_group do
39
+ auto_resource_fields(columns: columns, only: only)
40
+ end
41
+ elsif current_resource_field_group.forced_section.nil?
42
+ resource_field_section(columns) do
43
+ auto_resource_fields(columns: columns, only: only)
44
+ end
45
+ else
46
+ only = self.columns.collect{ |x| x.name.to_sym } - SKIPPED_ATTRIBUTES if only.size.zero?
47
+ self.columns.each do |att|
48
+ sym = att.name.to_sym
49
+ type = att.type
50
+ next unless only.include?(sym)
51
+
52
+ reflections.map{ |x| x[1] }
53
+ .filter{ |x| x.foreign_key == att.name }
54
+ .each do |r|
55
+ sym = r.name
56
+ type = :association
57
+ end
58
+
59
+ resource_field sym, type
60
+ end
61
+ end
62
+ end
63
+
64
+ def self.resource_field_group(key = :default, editable: true, &block)
65
+ self.resource_field_group_collection ||= []
66
+ self.current_resource_field_group = resource_field_group_collection.select{ |x| x.key == key}.first
67
+ unless current_resource_field_group.present?
68
+ self.current_resource_field_group = ResourceFieldGroup.new(key, editable)
69
+ self.resource_field_group_collection << self.current_resource_field_group
70
+ end
71
+ yield
72
+ self.current_resource_field_group = nil
73
+ end
74
+
75
+ def self.resource_field_section(columns = nil, &block)
76
+ self.current_resource_field_group.forced_section = self.current_resource_field_group.next_section(columns)
77
+ yield
78
+ self.current_resource_field_group.forced_section = nil
79
+ end
80
+
81
+ def self.resource_field(sym, type = :string, editable: nil)
82
+ self.current_resource_field_group.add_field(sym, type, editable)
83
+ end
84
+ end
85
+
86
+ class ResourceFieldGroup
87
+ attr_accessor :fields, :key, :editable, :forced_section, :sections
88
+
89
+ def initialize(key, editable)
90
+ self.key = key
91
+ self.editable = editable
92
+ self.fields = []
93
+ self.sections = []
94
+ end
95
+
96
+ def add_field(sym, type, editable)
97
+ e = editable.nil? ? self.editable : editable
98
+ section = forced_section || next_section
99
+ field = ResourceField.new(sym, type, e, self)
100
+ section.fields << field
101
+ fields << field
102
+ end
103
+
104
+ def next_section(columns = 1)
105
+ section = ResourceFieldSection.new(columns)
106
+ sections << section
107
+ section
108
+ end
109
+
110
+ def max_section_columns
111
+ sections.collect{ |x| x.columns }.max
112
+ end
113
+ end
114
+
115
+ class ResourceFieldSection
116
+ attr_accessor :fields, :columns
117
+
118
+ def initialize(columns = 1)
119
+ self.columns = columns
120
+ self.fields = []
121
+ end
122
+
123
+ def column_class
124
+ "col-md-#{12/columns}"
125
+ end
126
+ end
127
+
128
+ class ResourceField
129
+ attr_accessor :sym, :type, :editable
130
+
131
+ def initialize(sym, type, editable, group)
132
+ self.sym = sym
133
+ self.type = type
134
+ self.editable = editable
135
+ end
10
136
  end
11
137
  end
12
138
  end
@@ -32,14 +32,15 @@ module Olivander
32
32
  order(order_by[0], order_by[1]) if order_by.size == 2
33
33
  bulk_actions_col
34
34
  attributes.each do |key|
35
+ label = field_label_for(klazz, key)
35
36
  sym = key.gsub('_id', '').to_sym
36
37
  visible = show.include?(key) || !(default_hidden.include?(key) || hide.include?(key))
37
38
  if link_path.present? && sym == :id
38
39
  link_col sym, link_path, :id, visible: visible
39
40
  elsif link_path.present? && sym == :name
40
- link_col sym, link_path, %i[id name], visible: visible
41
+ link_col sym, link_path, :id, visible: visible
41
42
  else
42
- col sym, visible: visible
43
+ col sym, visible: visible, label: label
43
44
  end
44
45
  end
45
46
  actions_col
@@ -26,15 +26,32 @@ module Olivander
26
26
  actions = resource.is_a?(Class) ?
27
27
  (routed_resource.unpersisted_crud_actions | routed_resource.collection_actions.select{ |x| !x.crud_action }) :
28
28
  (resource.persisted? ? (routed_resource.persisted_crud_actions | routed_resource.member_actions.select{ |x| !x.crud_action }): [])
29
- actions.reject{ |a| a.sym == for_action }
29
+ actions = actions.reject{ |a| a.sym == for_action || !can?(a.sym, resource) }
30
+ preferred = %i[show edit destroy]
31
+ [].tap do |arr|
32
+ preferred.each do |p|
33
+ actions.each do |a|
34
+ arr << a if a.sym == p
35
+ end
36
+ end
37
+ arr &&= actions.reject{ |x| preferred.include?(x.sym) }
38
+ end
30
39
  end
31
40
 
32
41
  def resource_form_actions(route_builder, resource, for_action: :show)
33
- [].tap do |output|
34
- authorized_resource_actions(route_builder, resource, for_action: for_action).select{ |x| x.show_in_form }.each do |a|
35
- output << link_to(a.sym, {controller: a.controller, action: a.action}, method: a.verb, class: 'btn btn-tool', data: { turbo: true })
36
- end
37
- end.join('&nbsp;').html_safe
42
+ render partial: 'resource_form_actions', locals: { actions: authorized_resource_actions(route_builder, resource, for_action: for_action).select(&:show_in_form) }
43
+ end
44
+
45
+ def resource_form_action_label(resource, action)
46
+ return I18n.t("activerecord.actions.#{resource}.#{action}") if I18n.exists?("activerecord.actions.#{resource}.#{action}")
47
+ return I18n.t("activerecord.actions.#{action}") if I18n.exists?("activerecord.actions.#{action}")
48
+
49
+ action.to_s.titleize
50
+ end
51
+
52
+ def resource_field_group_label(resource_class, key)
53
+ i18n_key = "activerecord.attributes.#{resource_class.name.underscore}.resource_field_groups.#{key}"
54
+ I18n.exists?(i18n_key) ? I18n.t(i18n_key) : key.to_s.titleize
38
55
  end
39
56
 
40
57
  def current_user
@@ -44,5 +61,28 @@ module Olivander
44
61
  def current_ability
45
62
  controller.respond_to?(:current_ability) ? controller.current_ability : nil
46
63
  end
64
+
65
+ def resource_attributes(resource, effective_resource)
66
+ er_attributes = effective_resource&.model_attributes&.collect{ |x| x[0] }
67
+ return er_attributes if er_attributes.present? && er_attributes.size.positive?
68
+
69
+ resource.auto_form_attributes
70
+ end
71
+
72
+ def render_optional_partial partial
73
+ begin
74
+ render partial: partial
75
+ rescue ActionView::MissingTemplate
76
+ Rails.logger.debug "did not find partial: #{partial}"
77
+ nil
78
+ end
79
+ end
80
+
81
+ def field_label_for(resource_class, sym)
82
+ i18n_key = "activerecord.attributes.#{resource_class.name.underscore}.#{sym}"
83
+ return I18n.t(i18n_key) if I18n.exists?(i18n_key)
84
+
85
+ sym.to_s.titleize
86
+ end
47
87
  end
48
88
  end
@@ -2,16 +2,14 @@
2
2
  = simple_form_for(@resource) do |f|
3
3
  .card.card-primary
4
4
  .card-header
5
+ %h3.card-title= @resource
5
6
  .card-tools
6
7
  = resource_form_actions(@context.route_builder, @resource, for_action: action_name.to_sym)
7
8
  .card-body
8
9
  =f.error_notification
9
10
  =f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present?
10
- - @resource.auto_form_attributes.each do |a|
11
- .row
12
- .col-12
13
- = f.input a, disabled: read_only
11
+ = render Olivander::Components::ResourceFormComponent.new(@resource, f)
14
12
  .card-footer.text-right
15
13
  = link_to 'Cancel', @_effective_resource.action_path(:index), class: 'btn btn-secondary'
16
14
  - unless read_only
17
- = f.button :submit, class: 'btn btn-primary'
15
+ = f.button :submit, class: 'btn btn-primary'
@@ -0,0 +1,7 @@
1
+ - actions.each do |a|
2
+ = link_to controller: a.controller, action: a.action, method: a.verb, class: 'btn btn-tool', data: { turbo: true } do
3
+ - icon_key = "activerecord.actions.icons.#{a.sym}"
4
+ - if I18n.exists?(icon_key)
5
+ %i.fa{ class: I18n.t(icon_key)}
6
+ = resource_form_action_label(@resource, a.sym)
7
+ &nbsp;
@@ -1,12 +1,19 @@
1
1
  - resource = (@_effective_resource || Effective::Resource.new(controller_path))
2
2
  - @resource = instance_variable_get('@' + resource.name) if resource.name
3
3
 
4
+ = render_optional_partial 'show_before'
5
+
4
6
  - if @resource
5
7
  .row
6
8
  .col-12
7
- = render_resource_form(@resource)
9
+ .card.card-primary
10
+ .card-header
11
+ %h3.card-title= @resource.to_s
12
+ .card-tools
13
+ = resource_form_actions(@context.route_builder, @resource, for_action: action_name.to_sym)
14
+ .card-body
15
+ = render Olivander::Components::ResourceShowComponent.new(@resource, [])
16
+ .card-footer.text-right
17
+ = link_to 'Cancel', @_effective_resource.action_path(:index), class: 'btn btn-secondary'
8
18
 
9
- - begin
10
- = render partial: 'show_additional'
11
- - rescue ActionView::MissingTemplate
12
- - Rails.logger.debug "did not find additional show partial"
19
+ = render_optional_partial 'show_after'
@@ -2,4 +2,4 @@
2
2
  = dropdown(variation: :dropleft, btn_class: btn_class) do
3
3
  - authorized_resource_actions(route_builder, resource, for_action: action_name).select{ |x| x.show_in_datatable }.each do |a|
4
4
  - path = a.path_helper.is_a?(Proc) ? a.path_helper.call(resource) : send(a.path_helper, resource.id)
5
- = dropdown_link_to a.sym, path
5
+ = dropdown_link_to resource_form_action_label(resource, a.sym), path
@@ -42,7 +42,6 @@ module Olivander
42
42
  @submenu_items ||= [].tap do |arr|
43
43
  if visible
44
44
  @submenu_items_blocks.each do |block|
45
- Rails.logger.debug "invoking submenu item block on #{@key}"
46
45
  block.call.each { |item| arr << item if item.visible }
47
46
  end
48
47
  end
@@ -58,7 +57,6 @@ module Olivander
58
57
  @badges ||= [].tap do |arr|
59
58
  if visible
60
59
  @badges_blocks.each do |block|
61
- Rails.logger.debug "invoking badge block on #{@key}"
62
60
  block.call.each { |badge| arr << badge }
63
61
  end
64
62
  end
@@ -69,7 +67,6 @@ module Olivander
69
67
 
70
68
  def evaluate_conditions_block
71
69
  if @conditions_block
72
- Rails.logger.debug "invoking condition on #{@key}"
73
70
  @conditions_block.call
74
71
  else
75
72
  true
@@ -1,3 +1,3 @@
1
1
  module Olivander
2
- VERSION = "0.1.2.17"
2
+ VERSION = "0.1.2.18"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: five-two-nw-olivander
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2.17
4
+ version: 0.1.2.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Dennis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-13 00:00:00.000000000 Z
11
+ date: 2023-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chartkick
@@ -185,6 +185,10 @@ files:
185
185
  - app/assets/stylesheets/olivander/application.css
186
186
  - app/components/olivander/components/menu_item_component.html.haml
187
187
  - app/components/olivander/components/menu_item_component.rb
188
+ - app/components/olivander/components/resource_form_component.html.haml
189
+ - app/components/olivander/components/resource_form_component.rb
190
+ - app/components/olivander/components/resource_show_component.html.haml
191
+ - app/components/olivander/components/resource_show_component.rb
188
192
  - app/controllers/concerns/olivander/resources/auto_form_attributes.rb
189
193
  - app/controllers/concerns/olivander/resources/route_builder.rb
190
194
  - app/controllers/olivander/application_controller.rb
@@ -194,6 +198,7 @@ files:
194
198
  - app/mailers/olivander/application_mailer.rb
195
199
  - app/models/olivander/application_record.rb
196
200
  - app/views/application/_form.html.haml
201
+ - app/views/application/_resource_form_actions.html.haml
197
202
  - app/views/application/edit.html.haml
198
203
  - app/views/application/index.html.haml
199
204
  - app/views/application/new.html.haml