five-two-nw-olivander 0.2.0.1 → 0.2.0.3

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: 5d247c42715b68ca77e28f0b8d99f48b466d042ba197aad6a0fa5694d344d7d3
4
- data.tar.gz: 5d4f1e94e9c1d85378a0586481ecf276b34d65364fb341e95ae9020f437293f2
3
+ metadata.gz: 2e9d0ccea420078110d4af7de4d7eec3c0ac04e8a8a2533302d5792a1d599c58
4
+ data.tar.gz: '09b69957d70478ef092e8eff4a979ee867ac74c903fe1572793016d8ab26f531'
5
5
  SHA512:
6
- metadata.gz: 336beef33e5b2f9b3242a654d9de9b5cb2b19ef30b25b62ccb0b2bbb74753afbdddf027a289ec6dc65d873e9a53acab6998983f0394aa8162a1c516976c8f8f7
7
- data.tar.gz: aee825f87643bebac907ccfdf499b1f8d76f1a8e4049f58fa35856eaea663f8d175f808f7b04aa56b1ff0b704f7e1a7c322d6568e945b555c01423c0e6ec29e9
6
+ metadata.gz: 07ce6181e19ada53a8d78cf650c8b4cef82ccb4d38b33a09cca9b340d71567d2a4889f613c5986afb85fb6cc32b0b6010999f9af05fe40ab1ff7ff3a45f291e5
7
+ data.tar.gz: 67fbcc49d403734676c0f8d46052585ed70e127878bd6f4490f7d94f104d02aa8bcd7827da5d39957182a4a7b9dcc3947b41e69425189844a34e1812684efe15
@@ -1 +1,5 @@
1
1
  //= link_directory ../stylesheets/olivander .css
2
+ //= link controllers/datatable_index_charts_controller.js
3
+ //= link controllers/datatable_expandable_chart_controller.js
4
+ //= link controllers/turbo_flash_controller.js
5
+ //= link controllers/input_control_association_controller.js
@@ -0,0 +1,42 @@
1
+ (function() {
2
+ var destroySelect2s, logEvent;
3
+
4
+ $.extend(true, $.fn.dataTable.Buttons.defaults, {
5
+ dom: {
6
+ button: {
7
+ className: 'btn btn-outline-primary btn-sm'
8
+ }
9
+ }
10
+ });
11
+
12
+ $.extend(true, $.fn.dataTable.ext.classes, {
13
+ sProcessing: "dataTables_processing card overlay-wrapper"
14
+ });
15
+
16
+ destroySelect2s = function() {
17
+ $('.effective-datatables-filters').find('select').select2('destroy');
18
+ return $('.dataTables_wrapper').each(function(_, o) {
19
+ try {
20
+ return $(o).find('.dataTables_length select.select2-hidden-accessible').addClass('no-select2').removeAttr('name').select2('destroy');
21
+ } catch (error) {}
22
+ });
23
+ };
24
+
25
+ logEvent = function(e) {
26
+ return console.log(e);
27
+ };
28
+
29
+ $(document).ready(function(e) {
30
+ return destroySelect2s();
31
+ });
32
+
33
+ // $(document).ready(function(e) {
34
+ // return $('.effective-datatables-filters input').click(function() {
35
+ // var $form, $table;
36
+ // $form = $(event.currentTarget).closest('.effective-datatables-filters');
37
+ // $table = $('#' + $form.attr('aria-controls'));
38
+ // return $table.DataTable().draw();
39
+ // });
40
+ // });
41
+
42
+ }).call(this);
@@ -11,13 +11,25 @@ $.fn.select2.defaults.set('dropdownParent', $('#modal-root'))
11
11
  #
12
12
  # TODO: Recheck with the select2 GH issue and remove once this is fixed on their side
13
13
  #
14
- $(document).on 'select2:open', () =>
15
- document.querySelector('.select2-search__field').focus()
14
+ $(document).on 'select2:open', (evt) =>
15
+ try
16
+ evt.target.parent.querySelector('.select2-search__field').focus()
17
+ catch ex
18
+ evt.target.parentElement.querySelector('.select2-search__field').focus()
19
+
16
20
 
17
21
  initSelect2s = () -> $('select').not('.no-select2').each (k,v) =>
18
22
  $(v).select2({ dropdownParent: $(v).parent() })
19
23
 
20
- $(document).ready -> initSelect2s()
24
+ # $(document).ready -> initSelect2s()
21
25
  $(document).on 'show.bs.modal', (e) =>
22
26
  $('select').not('.no-select2').each (k,v) =>
23
27
  $(v).select2({ dropdownParent: $(v).parent() })
28
+
29
+ $(document).ready =>
30
+ $('.effective-datatables-filters').find('select').select2('destroy');
31
+ $('.dataTables_wrapper').each (_, o) =>
32
+ try
33
+ return $(o).find('.dataTables_length select.select2-hidden-accessible').addClass('no-select2').removeAttr('name').select2('destroy');
34
+ catch error
35
+ # don't care
@@ -19,3 +19,4 @@
19
19
  //= require "adminlte/dist/js/adminlte.js"
20
20
  //= require 'olivander/flash_toast'
21
21
  //= require "effective_datatables"
22
+ //= require "adminlte/datatable.fix.js"
@@ -0,0 +1,25 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ // Connects to data-controller="input-control-association"
4
+ export default class extends Controller {
5
+ connect() {
6
+ var self = this,
7
+ el = self.element;
8
+ if (!$(el).hasClass("select2-hidden-accessible")) {
9
+ $(el).select2({
10
+ dropdownParent: $(el).parent(),
11
+ ajax: {
12
+ url: el.dataset.collectionPath,
13
+ delay: 250,
14
+ minimumInputLength: 2,
15
+ dataType: 'json',
16
+ processResults: function(data) {
17
+ return { results: data.map(function(map) {
18
+ return { id: map.id, text: map.text || map.name || map.description };
19
+ }) };
20
+ }
21
+ }
22
+ })
23
+ }
24
+ }
25
+ }
@@ -5,9 +5,20 @@
5
5
  - section.fields.each do |field|
6
6
  %div{ class: section.column_class }
7
7
  - case field.type
8
- - when :association
9
- = @f.association field.sym, disabled: !field.editable, input_html: { data: { controller: "input-control-#{field.type}" } }
8
+ - when :association, :belongs_to_association, :has_many_association, :has_many_through_association, :has_and_belongs_to_many_reflection, :has_one_through_association
9
+ - reflection = @f.object.class.reflect_on_association(field.sym)
10
+ - controllers = "#{field.type}-#{@resource.class.name.underscore.gsub('/', '_')}-#{field.sym} input-control-association"
11
+ - begin
12
+ - collection_path = polymorphic_path(@resource.class.reflect_on_association(field.sym).klass, format: :json)
13
+ - rescue
14
+ - collection_path = ''
15
+ - collection = @f.object.send(field.sym)
16
+ - case field.type
17
+ - when :has_one_through_association
18
+ = @f.input field.sym, selected: collection, collection: [collection].flatten, disabled: !field.editable, input_html: { data: { collection_path: collection_path, controller: controllers } }
19
+ -else
20
+ = @f.association field.sym, collection: [collection].flatten, disabled: !field.editable, input_html: { data: { collection_path: collection_path, controller: controllers } }
10
21
  - when :boolean
11
22
  = @f.input field.sym, disabled: !field.editable, as: field.type.to_sym, input_html: { data: { controller: "input-control-#{field.type}" } }, wrapper: :checkbox
12
23
  - else
13
- = @f.input field.sym, disabled: !field.editable, as: field.type.to_sym, input_html: { data: { controller: "input-control-#{field.type}" } }
24
+ = @f.input field.sym, disabled: !field.editable, as: field.type.to_sym, input_html: { rows: 10, data: { controller: "input-control-#{field.type}" } }
@@ -23,14 +23,20 @@
23
23
  - when :boolean
24
24
  - icon_class = val ? 'fa-check text-success' : 'fa-times text-danger'
25
25
  %i.fa{ class: icon_class }
26
- - when :association
26
+ - when :association, :belongs_to_association, :has_many_association, :has_many_through_association, :has_and_belongs_to_many_reflection, :has_one_through_association
27
27
  - if val.present?
28
28
  - if val.is_a?(ActiveRecord::Associations::CollectionProxy)
29
29
  %ul
30
30
  - val.each do |val1|
31
- %li= link_to val1
31
+ - begin
32
+ %li= link_to val1
33
+ - rescue
34
+ %li= val1
32
35
  - else
33
- = link_to val if val.present?
36
+ - begin
37
+ = link_to val if val.present?
38
+ - rescue
39
+ = val if val.present?
34
40
  - when :file
35
41
  - if val.present?
36
42
  - if val.content_type.include?('image')
@@ -38,7 +44,6 @@
38
44
  - else
39
45
  = link_to val, val.expiring_url
40
46
  - else
41
- = f.type
42
47
  = val
43
48
  - (section.columns-slice.size).times do
44
49
  %th
@@ -0,0 +1,24 @@
1
+ module Olivander
2
+ module Resources
3
+ module ApplicationRecord
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ def self.audited_as klazz
8
+ # Rails.logger.debug "#{self.class.name} is audited as #{klazz.name}"
9
+ @@audited_user_class = klazz
10
+
11
+ belongs_to :created_by, class_name: klazz.name
12
+ belongs_to :updated_by, class_name: klazz.name
13
+
14
+ before_validation :set_audit_user
15
+ end
16
+
17
+ def set_audit_user
18
+ self.created_by ||= @@audited_user_class.current
19
+ self.updated_by = @@audited_user_class.current
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -33,16 +33,16 @@ module Olivander
33
33
  self.resource_field_group_collection
34
34
  end
35
35
 
36
- def self.auto_resource_fields(columns: 2, only: [])
36
+ def self.auto_resource_fields(columns: 2, only: [], except: [], editable: true)
37
37
  return unless ActiveRecord::Base.connection.table_exists?(table_name)
38
38
 
39
39
  if current_resource_field_group.nil?
40
40
  resource_field_group do
41
- auto_resource_fields(columns: columns, only: only)
41
+ auto_resource_fields(columns: columns, only: only, except: except, editable: editable)
42
42
  end
43
43
  elsif current_resource_field_group.forced_section.nil?
44
44
  resource_field_section(columns) do
45
- auto_resource_fields(columns: columns, only: only)
45
+ auto_resource_fields(columns: columns, only: only, except: except, editable: editable)
46
46
  end
47
47
  else
48
48
  if only.size.zero?
@@ -53,27 +53,30 @@ module Olivander
53
53
  only << attachment_definitions.select{ |x| x[0] } if respond_to?(:attachment_definitions)
54
54
  only = only.flatten - SKIPPED_ATTRIBUTES
55
55
  end
56
+ only = only - except
56
57
  only.each do |inc|
57
58
  self.columns.each do |att|
58
59
  sym = att.name.to_sym
59
60
  type = att.type
60
61
  next unless inc == sym
61
62
 
62
- resource_field sym, type
63
+ resource_field sym, type, editable: editable
63
64
  end
64
65
 
65
66
  reflections.map{ |x| x[1] }
66
67
  .filter{ |x| x.foreign_key == inc || x.name == inc }
67
68
  .each do |r|
68
- sym = r.name
69
- type = :association
70
- resource_field sym, type
69
+ begin
70
+ resource_field(r.name, r.association_class.name.demodulize.underscore.to_sym, editable: editable)
71
+ rescue NotImplementedError
72
+ resource_field(r.name, :association, editable: editable)
73
+ end
71
74
  end
72
75
 
73
76
  next unless respond_to?(:attachment_definitions)
74
77
 
75
78
  attachment_definitions.filter{ |x| x == inc }.each do |ad|
76
- resource_field ad[0], :file
79
+ resource_field ad[0], :file, editable: editable
77
80
  end
78
81
  end
79
82
  end
@@ -0,0 +1,39 @@
1
+ module Olivander
2
+ module Resources
3
+ module CrudController
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ include Effective::CrudController
8
+ layout 'olivander/adminlte/main'
9
+
10
+ def index
11
+ if request.format == :json && params[:_type].present? && params[:_type] == 'query'
12
+ index_search
13
+ else
14
+ super
15
+ end
16
+ end
17
+
18
+ def index_search
19
+ self.resources ||= resource_scope.all if resource_scope.respond_to?(:all)
20
+ if resource_scope.respond_to?(:search_for)
21
+ self.resources = self.resources.search_for(params[:term])
22
+ else
23
+ k = resources.klass
24
+ like_term = "%#{ActiveRecord::Base.sanitize_sql_like(params[:term])}%"
25
+ fields = %w[name title description text].keep_if{ |field| k.respond_to?(field) }
26
+ clauses = fields.map{ |field| "#{field} ilike '#{like_term}'" }.join(' or ')
27
+ orders = fields.join(', ')
28
+ self.resources = self.resources.where(clauses).order(orders) if clauses.length.positive?
29
+ end
30
+ self.resources = self.resources.limit(25)
31
+ end
32
+
33
+ def permitted_params
34
+ params.fetch(resource_klass.name.underscore.gsub('/', '_').to_sym, {}).permit!
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -3,12 +3,12 @@ module Olivander
3
3
  class ResourceAction
4
4
  attr_accessor :sym, :action, :verb, :confirm, :turbo_frame, :collection,
5
5
  :controller, :crud_action, :show_in_form, :show_in_datatable,
6
- :no_route, :path_helper, :confirm_with
6
+ :no_route, :path_helper, :confirm_with, :primary
7
7
 
8
8
  def initialize(sym, action: nil, controller: nil, verb: :get, confirm: false,
9
9
  turbo_frame: nil, collection: false, crud_action: false,
10
10
  show_in_form: true, show_in_datatable: true, no_route: false,
11
- path_helper: nil, confirm_with: nil)
11
+ path_helper: nil, confirm_with: nil, primary: nil)
12
12
  self.sym = sym
13
13
  self.action = action || sym
14
14
  self.controller = controller
@@ -22,6 +22,7 @@ module Olivander
22
22
  self.no_route = no_route
23
23
  self.path_helper = path_helper
24
24
  self.confirm_with = confirm_with
25
+ self.primary = primary || crud_action
25
26
  end
26
27
 
27
28
  def args_hash(options = nil)
@@ -131,7 +132,7 @@ module Olivander
131
132
 
132
133
  def action(sym, verb: :get, confirm: false, turbo_frame: nil, collection: false, show_in_datatable: true,
133
134
  show_in_form: true, no_route: false, controller: nil, action: nil, path_helper: nil,
134
- confirm_with: nil
135
+ confirm_with: nil, primary: nil
135
136
  )
136
137
  raise 'Must be invoked in a resource block' unless current_resource.present?
137
138
 
@@ -139,7 +140,7 @@ module Olivander
139
140
  current_resource.actions << ResourceAction.new(
140
141
  sym, action: action, controller: controller, verb: verb, confirm: confirm, turbo_frame: turbo_frame, collection: collection,
141
142
  show_in_datatable: show_in_datatable, show_in_form: show_in_form, no_route: no_route, path_helper: path_helper,
142
- confirm_with: confirm_with
143
+ confirm_with: confirm_with, primary: primary
143
144
  )
144
145
  end
145
146
 
@@ -73,6 +73,14 @@ module Olivander
73
73
  render partial: 'resource_form_actions', locals: { actions: authorized_resource_actions(resource, for_action: for_action).select(&:show_in_form) }
74
74
  end
75
75
 
76
+ def resource_form_action_tooltip(resource, action)
77
+ key = resource.class.name.underscore
78
+ return I18n.t("activerecord.actions.#{key}.#{action}-tooltip") if I18n.exists?("activerecord.actions.#{key}.#{action}-tooltip")
79
+ return I18n.t("activerecord.actions.#{action}-tooltip") if I18n.exists?("activerecord.actions.#{action}-tooltip")
80
+
81
+ action.to_s.titleize
82
+ end
83
+
76
84
  def resource_form_action_label(resource, action)
77
85
  key = resource.class.name.underscore
78
86
  return I18n.t("activerecord.actions.#{key}.#{action}") if I18n.exists?("activerecord.actions.#{key}.#{action}")
@@ -95,7 +103,7 @@ module Olivander
95
103
  end
96
104
 
97
105
  def current_user
98
- Olivander::CurrentContext.user || OpenStruct.new({ display_name: 'No User Set' })
106
+ Olivander::CurrentContext.user
99
107
  end
100
108
 
101
109
  def current_ability
@@ -0,0 +1,41 @@
1
+ class CustomFormBuilder < SimpleForm::FormBuilder
2
+ def initialize(*)
3
+ super
4
+ end
5
+
6
+ def association(association, options = {}, &block)
7
+ resolve_custom_input_association(association, options)
8
+ super(association, options, &block)
9
+ end
10
+
11
+ def resolve_custom_input_association(association, options)
12
+ return if options[:as].present?
13
+
14
+ [
15
+ "#{object.class.name.demodulize.underscore}_#{association.to_s}".to_sym, association
16
+ ].each do |key|
17
+ camelized = "#{key.to_s.camelize}Input"
18
+ mapping = attempt_mapping_with_custom_namespace(camelized) ||
19
+ attempt_mapping(camelized, Object) ||
20
+ attempt_mapping(camelized, self.class)
21
+
22
+ next unless mapping.present?
23
+
24
+ options[:as] = key
25
+ break
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def fetch_association_collection(reflection, options)
32
+ options_method = "options_for_#{reflection.name}".to_sym
33
+ if object.respond_to?(options_method) then
34
+ options.fetch(:collection) do
35
+ object.send(options_method)
36
+ end
37
+ else
38
+ super(reflection, options)
39
+ end
40
+ end
41
+ end
@@ -1,5 +1,5 @@
1
1
  - read_only = !%w[new create edit update].include?(action_name)
2
- = simple_form_for(@resource) do |f|
2
+ = simple_form_for(@resource, builder: CustomFormBuilder) do |f|
3
3
  .card.card-primary
4
4
  .card-header
5
5
  %h3.card-title= @resource.to_s.blank? ? @resource.model_name.human : @resource
@@ -4,21 +4,27 @@
4
4
  -# - data = a.turbo_frame.present? ? { turbo: true, turbo_frame: a.turbo_frame } : {}
5
5
  -# = dropdown_link_to resource_form_action_label(resource, a.sym), path, data: data
6
6
  - actions = authorized_resource_actions(resource, for_action: action_name).select{ |x| x.show_in_datatable }
7
- - crud_actions = actions.select{ |a| a.crud_action }
8
- - non_crud_actions = actions.select{ |a| !a.crud_action }
7
+ - primary_actions = actions.select{ |a| a.primary }
8
+ - non_primary_actions = actions.select{ |a| !a.primary }
9
9
  .btn-group
10
- - if non_crud_actions.size.positive?
10
+ - if non_primary_actions.size.positive?
11
11
  .btn-group
12
12
  %button.btn.btn-sm.dropdown-toggle{ type: :button, data: { toggle: 'dropdown' }}
13
13
  %ul.dropdown-menu
14
- - non_crud_actions.each do |a|
14
+ - non_primary_actions.each do |a|
15
15
  - path = a.path_helper.is_a?(Proc) ? a.path_helper.call(resource) : send(a.path_helper, resource.id)
16
- - data = a.turbo_frame.present? ? { turbo: true, turbo_frame: a.turbo_frame } : {}
16
+ - hash = {}
17
+ - data = a.turbo_frame.present? ? { turbo: true, turbo_frame: a.turbo_frame, turbo_method: a.verb } : {}
18
+ - hash[:data] = data
19
+ - hash[:method] = a.verb unless a.turbo_frame.present?
17
20
  %li
18
- = dropdown_link_to resource_form_action_label(resource, a.sym), path, data: data, method: a.verb
19
- - crud_actions.each do |a|
21
+ = dropdown_link_to resource_form_action_label(resource, a.sym), path, hash
22
+ - primary_actions.each do |a|
20
23
  - path = a.path_helper.is_a?(Proc) ? a.path_helper.call(resource) : send(a.path_helper, resource.id)
21
24
  - icon_class = (a.verb == :delete ? '' : '')
22
- = link_to path, a.args_hash(title: resource_form_action_label(resource, a.sym), class: "btn btn-sm #{icon_class}") do
23
- %i{ class: resource_form_action_icon(resource, a.sym), style: 'display: block; font-size: 10px' }
24
- %span{ style: 'font-size: 12px' }= resource_form_action_label(resource, a.sym)
25
+ = link_to path, a.args_hash(title: resource_form_action_tooltip(resource, a.sym), class: "btn btn-sm #{icon_class}") do
26
+ - action_label = resource_form_action_label(resource, a.sym)
27
+ - icon_font_size = action_label.blank? ? '18px' : '10px'
28
+ %i{ class: resource_form_action_icon(resource, a.sym), style: "display: block; font-size: #{icon_font_size}" }
29
+ - unless action_label.blank?
30
+ %span{ style: 'font-size: 12px' }= action_label
@@ -101,20 +101,21 @@
101
101
  -# %a.dropdown-item.dropdown-footer{:href => "#"} See All Notifications
102
102
  %li.nav-item.dropdown.user-menu
103
103
  %a.nav-link.dropdown-toggle{"data-toggle" => "dropdown", :href => "#"}
104
- %img.user-image.img-circle.elevation-2{:alt => "User Image", :src => image_path(user_image_path(current_user))}/
104
+ %img.user-image.img-circle.elevation-2{:alt => "User Image", :src => image_path(user_image_path(Olivander::CurrentContext.user))}/
105
105
 
106
- %span.d-none.d-md-inline= current_user.display_name
106
+ %span.d-none.d-md-inline= Olivander::CurrentContext.user.display_name
107
107
  %ul.dropdown-menu.dropdown-menu-lg.dropdown-menu-right
108
108
  / User image
109
109
  %li.user-header.bg-primary
110
- %img.img-circle.elevation-2{:alt => "User Image", src: image_path(user_image_path(current_user))}/
111
- %p= current_user.display_name
110
+ %img.img-circle.elevation-2{:alt => "User Image", src: image_path(user_image_path(Olivander::CurrentContext.user))}/
111
+ %p= Olivander::CurrentContext.user.display_name
112
112
  / Menu Footer
113
- %li.user-footer
114
- = link_to user_path(current_user), class: 'btn btn-default btn-flat' do
115
- Profile
116
- = link_to Olivander::CurrentContext.application_context.sign_out_path, method: :delete, class: 'btn btn-default btn-flat float-right' do
117
- Sign out
113
+ - unless Olivander::CurrentContext.user.is_a?(OpenStruct)
114
+ %li.user-footer
115
+ = link_to polymorphic_path(Olivander::CurrentContext.user), class: 'btn btn-default btn-flat' do
116
+ Profile
117
+ = link_to Olivander::CurrentContext.application_context.sign_out_path, method: :delete, class: 'btn btn-default btn-flat float-right' do
118
+ Sign out
118
119
  %li.nav-item
119
120
  %a.nav-link{title: 'Full Screen Mode', "data-widget" => "fullscreen", :href => "#", :role => "button"}
120
121
  %i.fas.fa-expand-arrows-alt
@@ -70,16 +70,49 @@ SimpleForm.setup do |config|
70
70
  config.wrappers :checkbox, class: "form-check",
71
71
  hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b|
72
72
  b.use :html5
73
- b.use :placeholder
74
- b.optional :maxlength
75
- b.optional :minlength
76
- b.optional :pattern
77
- b.optional :min_max
78
73
  b.optional :readonly
79
- b.use :input, class: 'form-check-input'
80
- b.use :label #, class: 'form-control'
81
- b.use :hint, wrap_with: { tag: :span, class: :hint }
82
- b.use :error, wrap_with: { tag: :span, class: "text-danger" }
74
+ b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
75
+ ba.use :label_text
76
+ end
77
+ b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
78
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
79
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
80
+ end
81
+
82
+ # vertical input for boolean
83
+ config.wrappers :vertical_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
84
+ b.use :html5
85
+ b.optional :readonly
86
+ b.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb|
87
+ bb.use :input, class: 'form-check-input' #, error_class: 'is-invalid', valid_class: 'is-valid'
88
+ bb.use :label, class: 'form-check-label'
89
+ bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
90
+ bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
91
+ end
92
+ end
93
+
94
+ # vertical input for radio buttons and check boxes
95
+ config.wrappers :vertical_collection, item_wrapper_class: 'form-check', item_label_class: 'form-check-label', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
96
+ b.use :html5
97
+ b.optional :readonly
98
+ b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
99
+ ba.use :label_text
100
+ end
101
+ b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
102
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
103
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
104
+ end
105
+
106
+ # vertical input for inline radio buttons and check boxes
107
+ config.wrappers :vertical_collection_inline, item_wrapper_class: 'form-check form-check-inline', item_label_class: 'form-check-label', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
108
+ b.use :html5
109
+ b.optional :readonly
110
+ b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
111
+ ba.use :label_text
112
+ end
113
+ b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
114
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
115
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
83
116
  end
84
117
 
85
118
  config.wrappers :switch, class: "custom-control custom-switch",
@@ -170,10 +203,24 @@ SimpleForm.setup do |config|
170
203
  # Custom wrappers for input types. This should be a hash containing an input
171
204
  # type as key and the wrapper that will be used for all inputs with specified type.
172
205
  # config.wrapper_mappings = { string: :prepend }
206
+ config.wrapper_mappings = {
207
+ boolean: :vertical_boolean,
208
+ check_boxes: :check_box,
209
+ # date: :horizontal_multi_select,
210
+ # datetime: :horizontal_multi_select,
211
+ # file: :horizontal_file,
212
+ # radio_buttons: :horizontal_collection,
213
+ # range: :horizontal_range,
214
+ # time: :horizontal_multi_select
215
+ }
173
216
 
174
217
  # Namespaces where SimpleForm should look for custom input classes that
175
218
  # override default inputs.
176
- # config.custom_inputs_namespaces << "CustomInputs"
219
+ Dir.glob('app/inputs/**/')
220
+ .map{ |x| x.gsub('app/inputs/', '').split('/').reject(&:blank?).join('/').camelize }
221
+ .reject(&:blank?).each do |d|
222
+ config.custom_inputs_namespaces << d
223
+ end
177
224
 
178
225
  # Default priority for time_zone inputs.
179
226
  # config.time_zone_priority = nil
@@ -2,23 +2,17 @@ module Olivander
2
2
  class ApplicationContext
3
3
  attr_accessor :name, :logo, :company, :menu_items, :route_builder, :sign_out_path, :sidebar_background_class
4
4
 
5
- def self.default
6
- ctx = ApplicationContext.new
7
- ctx.company.name = 'Company Name'
5
+ def initialize(**kwargs)
6
+ self.name = kwargs[:name] || ENV['OLIVANDER_APP_NAME'] || 'Application Name'
7
+ self.logo = kwargs[:logo] || Logo.new(url: kwargs[:logo_url], alt: kwargs[:logo_alt])
8
+ self.company = kwargs[:company] || Company.new(name: kwargs[:company_name], url: kwargs[:company_url])
9
+ self.sign_out_path = kwargs[:sign_out_path] || '/sign_out'
10
+ self.menu_items = kwargs[:menu_items] || []
8
11
  begin
9
- ctx.route_builder = RouteBuilder.new
10
- rescue
11
- ctx.route_builder = OpenStruct.new(resources: [])
12
+ self.route_builder = RouteBuilder.new
13
+ rescue NameError
14
+ self.route_builder = OpenStruct.new(resources: {})
12
15
  end
13
- ctx
14
- end
15
-
16
- def initialize(name: 'Application Name', logo: Logo.new, company: Company.new, sign_out_path: '/sign_out', menu_items: [])
17
- self.name = name
18
- self.logo = logo
19
- self.company = company
20
- self.sign_out_path = sign_out_path
21
- self.menu_items = menu_items
22
16
  end
23
17
 
24
18
  def visible_modules
@@ -41,18 +35,18 @@ module Olivander
41
35
  class Logo
42
36
  attr_accessor :url, :alt
43
37
 
44
- def initialize(url: nil, alt: 'Logo')
45
- self.url = url
46
- self.alt = alt
38
+ def initialize(**kwargs)
39
+ self.url = kwargs[:url] || ENV['OLIVANDER_LOGO_URL'] || '/images/olivander_logo.png'
40
+ self.alt = kwargs[:alt] || ENV['OLIVANDER_LOGO_ALT'] || 'Logo Image'
47
41
  end
48
42
  end
49
43
 
50
44
  class Company
51
45
  attr_accessor :name, :url
52
46
 
53
- def initialize(name: nil, url: nil)
54
- self.url = url
55
- self.name = name
47
+ def initialize(**kwargs)
48
+ self.url = kwargs[:url] || ENV['OLIVANDER_COMPANY_URL'] || '/'
49
+ self.name = kwargs[:name] || ENV['OLIVANDER_COMPANY_NAME'] || 'Company Name'
56
50
  end
57
51
  end
58
52
  end
@@ -61,8 +55,30 @@ module Olivander
61
55
  attribute :application_context
62
56
  attribute :user, :ability
63
57
 
64
- def application_context
65
- @application_context ||= ::Olivander::ApplicationContext.default
58
+ def build(&block)
59
+ self.application_context ||= ::Olivander::ApplicationContext.new
60
+ self.user ||= build_dummy_user
61
+ self.ability ||= build_dummy_ability
62
+ yield(self, application_context, user, ability) if block_given?
63
+ self
64
+ end
65
+
66
+ private
67
+
68
+ def build_dummy_user
69
+ OpenStruct.new({ display_name: 'No User Set' })
70
+ end
71
+
72
+ def build_dummy_ability
73
+ Class.new do
74
+ def can?(_action, _resource)
75
+ true
76
+ end
77
+
78
+ def authorize!(_action, _resource)
79
+ true
80
+ end
81
+ end.new
66
82
  end
67
83
  end
68
84
  end
@@ -1,3 +1,3 @@
1
1
  module Olivander
2
- VERSION = '0.2.0.1'.freeze
2
+ VERSION = '0.2.0.3'.freeze
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.2.0.1
4
+ version: 0.2.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Dennis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-13 00:00:00.000000000 Z
11
+ date: 2024-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chartkick
@@ -175,6 +175,7 @@ files:
175
175
  - app/assets/images/default-150x150.png
176
176
  - app/assets/images/icons.png
177
177
  - app/assets/javascripts/adminlte.js
178
+ - app/assets/javascripts/adminlte/datatable.fix.js
178
179
  - app/assets/javascripts/adminlte/dist/css/adminlte.min.css
179
180
  - app/assets/javascripts/adminlte/dist/js/adminlte.js
180
181
  - app/assets/javascripts/adminlte/plugins/bootstrap/js/bootstrap.bundle.min.js
@@ -208,6 +209,7 @@ files:
208
209
  - app/assets/javascripts/adminlte/select2_defaults.coffee
209
210
  - app/assets/javascripts/controllers/datatable_expandable_chart_controller.js
210
211
  - app/assets/javascripts/controllers/datatable_index_charts_controller.js
212
+ - app/assets/javascripts/controllers/input_control_association_controller.js
211
213
  - app/assets/javascripts/controllers/turbo_flash_controller.js
212
214
  - app/assets/javascripts/olivander/flash_toast.js
213
215
  - app/assets/stylesheets/adminlte.css
@@ -228,15 +230,17 @@ files:
228
230
  - app/components/olivander/components/table_portlet_component.html.haml
229
231
  - app/components/olivander/components/table_portlet_component.rb
230
232
  - app/components/olivander/components/table_portlet_component/table_component.html.haml
233
+ - app/controllers/concerns/olivander/resources/application_record.rb
231
234
  - app/controllers/concerns/olivander/resources/auto_form_attributes.rb
235
+ - app/controllers/concerns/olivander/resources/crud_controller.rb
232
236
  - app/controllers/concerns/olivander/resources/route_builder.rb
233
237
  - app/controllers/olivander/application_controller.rb
234
238
  - app/datatables/olivander/datatable.rb
235
239
  - app/helpers/olivander/application_helper.rb
240
+ - app/inputs/custom_form_builder.rb
236
241
  - app/inputs/date_time_input.rb
237
242
  - app/jobs/olivander/application_job.rb
238
243
  - app/mailers/olivander/application_mailer.rb
239
- - app/models/olivander/application_record.rb
240
244
  - app/views/application/_form.html.haml
241
245
  - app/views/application/_resource_form_actions.html.haml
242
246
  - app/views/application/edit.html.haml
@@ -1,20 +0,0 @@
1
- module Olivander
2
- class ApplicationRecord < ActiveRecord::Base
3
- self.abstract_class = true
4
-
5
- def self.audited_as klazz
6
- # Rails.logger.debug "#{self.class.name} is audited as #{klazz.name}"
7
- @@audited_user_class = klazz
8
-
9
- belongs_to :created_by, class_name: klazz.name
10
- belongs_to :updated_by, class_name: klazz.name
11
-
12
- before_validation :set_audit_user
13
- end
14
-
15
- def set_audit_user
16
- self.created_by ||= @@audited_user_class.current
17
- self.updated_by = @@audited_user_class.current
18
- end
19
- end
20
- end