five-two-nw-olivander 0.1.2.17 → 0.1.2.18

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 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