five-two-nw-olivander 0.2.0.0 → 0.2.0.2
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 +4 -4
- data/app/assets/config/olivander_manifest.js +4 -0
- data/app/assets/javascripts/adminlte/select2_defaults.coffee +3 -3
- data/app/assets/javascripts/controllers/input_control_association_controller.js +25 -0
- data/app/components/olivander/components/resource_form_component.html.haml +4 -2
- data/app/controllers/concerns/olivander/resources/application_record.rb +24 -0
- data/app/controllers/concerns/olivander/resources/auto_form_attributes.rb +6 -8
- data/app/controllers/concerns/olivander/resources/crud_controller.rb +38 -0
- data/app/datatables/olivander/datatable.rb +1 -2
- data/app/helpers/olivander/application_helper.rb +8 -8
- data/app/inputs/custom_form_builder.rb +41 -0
- data/app/views/application/_form.html.haml +2 -2
- data/app/views/application/index.html.haml +1 -1
- data/app/views/application/show.html.haml +1 -1
- data/app/views/effective/resource/_actions_dropleft.html.haml +2 -3
- data/app/views/layouts/olivander/adminlte/_footer.html.haml +1 -1
- data/app/views/layouts/olivander/adminlte/_navbar.html.haml +2 -2
- data/app/views/layouts/olivander/adminlte/_sidebar.html.haml +2 -2
- data/app/views/layouts/olivander/adminlte/login.html.haml +1 -1
- data/app/views/layouts/olivander/adminlte/main.html.haml +0 -1
- data/config/initializers/simple_form.rb +57 -10
- data/lib/olivander/application_context.rb +26 -18
- data/lib/olivander/version.rb +1 -1
- metadata +6 -3
- data/app/models/olivander/application_record.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76ede3e2ce50954cf786b9b30fabed5c294bb1b174a78f8493e331be73eb1b14
|
4
|
+
data.tar.gz: 7f23d18fe4144d9a0ce8829be386033a8e29e116186590d00c66339adbfdbddc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9fffc213421e65a2c263771e6071d7ff4f8ca97b74b2f9bb30eb7be49180cb97da2beda9bebd2b68e7117504a35b8ecfadfa39056ab17950a69d5dc076ba837f
|
7
|
+
data.tar.gz: 17a316a14e4406b136158ef9100bca6de6249e3ac96eb600dab8983d7f8b6cd21d5a6723e6d2ee3d1715ee4d0529151b82a5948402de517b5af37565f45f6832
|
@@ -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
|
@@ -11,13 +11,13 @@ $.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
|
-
|
14
|
+
$(document).on 'select2:open', (evt) =>
|
15
|
+
evt.target.parent.querySelector('.select2-search__field').focus()
|
16
16
|
|
17
17
|
initSelect2s = () -> $('select').not('.no-select2').each (k,v) =>
|
18
18
|
$(v).select2({ dropdownParent: $(v).parent() })
|
19
19
|
|
20
|
-
$(document).ready -> initSelect2s()
|
20
|
+
# $(document).ready -> initSelect2s()
|
21
21
|
$(document).on 'show.bs.modal', (e) =>
|
22
22
|
$('select').not('.no-select2').each (k,v) =>
|
23
23
|
$(v).select2({ dropdownParent: $(v).parent() })
|
@@ -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
|
+
}
|
@@ -6,8 +6,10 @@
|
|
6
6
|
%div{ class: section.column_class }
|
7
7
|
- case field.type
|
8
8
|
- when :association
|
9
|
-
= @
|
9
|
+
- controllers = "#{field.type}-#{@resource.class.name.underscore}-#{field.sym} input-control-#{field.type}"
|
10
|
+
- collection_path = polymorphic_path(@resource.class.reflect_on_association(field.sym).klass, format: :json)
|
11
|
+
= @f.association field.sym, collection: [@f.object.send(field.sym)].flatten, disabled: !field.editable, input_html: { data: { collection_path: collection_path, controller: controllers } }
|
10
12
|
- when :boolean
|
11
13
|
= @f.input field.sym, disabled: !field.editable, as: field.type.to_sym, input_html: { data: { controller: "input-control-#{field.type}" } }, wrapper: :checkbox
|
12
14
|
- else
|
13
|
-
= @f.input field.sym, disabled: !field.editable, as: field.type.to_sym, input_html: { data: { controller: "input-control-#{field.type}" } }
|
15
|
+
= @f.input field.sym, disabled: !field.editable, as: field.type.to_sym, input_html: { rows: 10, data: { controller: "input-control-#{field.type}" } }
|
@@ -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: [], 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, 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, editable: editable)
|
46
46
|
end
|
47
47
|
else
|
48
48
|
if only.size.zero?
|
@@ -59,21 +59,19 @@ module Olivander
|
|
59
59
|
type = att.type
|
60
60
|
next unless inc == sym
|
61
61
|
|
62
|
-
resource_field sym, type
|
62
|
+
resource_field sym, type, editable: editable
|
63
63
|
end
|
64
64
|
|
65
65
|
reflections.map{ |x| x[1] }
|
66
66
|
.filter{ |x| x.foreign_key == inc || x.name == inc }
|
67
67
|
.each do |r|
|
68
|
-
|
69
|
-
type = :association
|
70
|
-
resource_field sym, type
|
68
|
+
resource_field r.name, :association, editable: editable
|
71
69
|
end
|
72
70
|
|
73
71
|
next unless respond_to?(:attachment_definitions)
|
74
72
|
|
75
73
|
attachment_definitions.filter{ |x| x == inc }.each do |ad|
|
76
|
-
resource_field ad[0], :file
|
74
|
+
resource_field ad[0], :file, editable: editable
|
77
75
|
end
|
78
76
|
end
|
79
77
|
end
|
@@ -0,0 +1,38 @@
|
|
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 params[:term].present?
|
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
|
+
end
|
31
|
+
|
32
|
+
def permitted_params
|
33
|
+
params.fetch(resource_klass.name.underscore.gsub('/', '_').to_sym, {}).permit!
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -24,8 +24,7 @@ module Olivander
|
|
24
24
|
column_attributes &&= only if only.size.positive?
|
25
25
|
column_attributes -= except if except.size.positive?
|
26
26
|
resources_sym = klazz.table_name.to_sym
|
27
|
-
bulk_action_list =
|
28
|
-
|
27
|
+
bulk_action_list = Olivander::CurrentContext.application_context.route_builder.resources[resources_sym]&.datatable_bulk_actions || []
|
29
28
|
default_hidden = %w[
|
30
29
|
id created updated created_at updated_at
|
31
30
|
deleted_at current_user current_action
|
@@ -34,10 +34,10 @@ module Olivander
|
|
34
34
|
user.avatar_path
|
35
35
|
end
|
36
36
|
|
37
|
-
def authorized_resource_actions(
|
37
|
+
def authorized_resource_actions(resource, for_action: :show)
|
38
38
|
raw_name = resource.is_a?(Class) ? resource.name : resource.class.name
|
39
39
|
plural_name = raw_name.demodulize.underscore.pluralize
|
40
|
-
routed_resource = route_builder.resources[plural_name.to_sym]
|
40
|
+
routed_resource = Olivander::CurrentContext.application_context.route_builder.resources[plural_name.to_sym]
|
41
41
|
return [] if routed_resource.nil?
|
42
42
|
|
43
43
|
actions = if resource.is_a?(Class)
|
@@ -69,8 +69,8 @@ module Olivander
|
|
69
69
|
respond_to?('can?') ? can?(action, resource) : true
|
70
70
|
end
|
71
71
|
|
72
|
-
def resource_form_actions(
|
73
|
-
render partial: 'resource_form_actions', locals: { actions: authorized_resource_actions(
|
72
|
+
def resource_form_actions(resource, for_action: :show)
|
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
76
|
def resource_form_action_label(resource, action)
|
@@ -95,11 +95,11 @@ module Olivander
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def current_user
|
98
|
-
|
98
|
+
Olivander::CurrentContext.user || OpenStruct.new({ display_name: 'No User Set' })
|
99
99
|
end
|
100
100
|
|
101
101
|
def current_ability
|
102
|
-
|
102
|
+
Olivander::CurrentContext.ability
|
103
103
|
end
|
104
104
|
|
105
105
|
def resource_attributes(resource, effective_resource)
|
@@ -130,7 +130,7 @@ module Olivander
|
|
130
130
|
end
|
131
131
|
|
132
132
|
def sidebar_context_name
|
133
|
-
[
|
133
|
+
[Olivander::CurrentContext.application_context.name, sidebar_context_suffix&.upcase].reject{ |x| x.blank? or x == 'PRODUCTION' }.join(' ')
|
134
134
|
end
|
135
135
|
|
136
136
|
def sidebar_context_suffix
|
@@ -144,7 +144,7 @@ module Olivander
|
|
144
144
|
end
|
145
145
|
|
146
146
|
def sidebar_background_class
|
147
|
-
|
147
|
+
Olivander::CurrentContext.application_context.sidebar_background_class ||
|
148
148
|
ENV['SIDEBAR_BACKGROUND_CLASS'] ||
|
149
149
|
(is_dev_environment? ? 'bg-danger' : 'bg-info')
|
150
150
|
end
|
@@ -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,10 +1,10 @@
|
|
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
|
6
6
|
.card-tools
|
7
|
-
= resource_form_actions(@
|
7
|
+
= resource_form_actions(@resource, for_action: action_name.to_sym)
|
8
8
|
.card-body
|
9
9
|
=f.error_notification
|
10
10
|
=f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present?
|
@@ -33,7 +33,7 @@
|
|
33
33
|
.card-header
|
34
34
|
%h3.card-title= page_title
|
35
35
|
.card-tools
|
36
|
-
= resource_form_actions(
|
36
|
+
= resource_form_actions(resource.klass, for_action: :index)
|
37
37
|
.card-body
|
38
38
|
- if @datatable
|
39
39
|
= content_for :datatable
|
@@ -10,7 +10,7 @@
|
|
10
10
|
.card-header
|
11
11
|
%h3.card-title= @resource.to_s
|
12
12
|
.card-tools
|
13
|
-
= resource_form_actions(@
|
13
|
+
= resource_form_actions(@resource, for_action: action_name.to_sym)
|
14
14
|
.card-body
|
15
15
|
= render_optional_partial 'show_inside_before'
|
16
16
|
= render Olivander::Components::ResourceShowComponent.new(@resource, [])
|
@@ -1,10 +1,9 @@
|
|
1
|
-
- route_builder = @context&.route_builder || datatable.class::ROUTE_BUILDER
|
2
1
|
-# = dropdown(variation: :dropleft, btn_class: btn_class) do
|
3
|
-
-# - authorized_resource_actions(
|
2
|
+
-# - authorized_resource_actions(resource, for_action: action_name).select{ |x| x.show_in_datatable }.each do |a|
|
4
3
|
-# - path = a.path_helper.is_a?(Proc) ? a.path_helper.call(resource) : send(a.path_helper, resource.id)
|
5
4
|
-# - data = a.turbo_frame.present? ? { turbo: true, turbo_frame: a.turbo_frame } : {}
|
6
5
|
-# = dropdown_link_to resource_form_action_label(resource, a.sym), path, data: data
|
7
|
-
- actions = authorized_resource_actions(
|
6
|
+
- actions = authorized_resource_actions(resource, for_action: action_name).select{ |x| x.show_in_datatable }
|
8
7
|
- crud_actions = actions.select{ |a| a.crud_action }
|
9
8
|
- non_crud_actions = actions.select{ |a| !a.crud_action }
|
10
9
|
.btn-group
|
@@ -2,7 +2,7 @@
|
|
2
2
|
%strong
|
3
3
|
Copyright © #{Date.current.year}
|
4
4
|
= succeed "." do
|
5
|
-
= link_to
|
5
|
+
= link_to Olivander::CurrentContext.application_context.company.name, Olivander::CurrentContext.application_context.company.url
|
6
6
|
All rights reserved.
|
7
7
|
.float-right.d-none.d-sm-inline-block
|
8
8
|
.text-small
|
@@ -5,7 +5,7 @@
|
|
5
5
|
%li.nav-item
|
6
6
|
%a.nav-link{"data-widget" => "pushmenu", :href => "#", :role => "button", 'data-enable-remember': "true"}
|
7
7
|
%i.fas.fa-bars
|
8
|
-
-
|
8
|
+
- Olivander::CurrentContext.application_context.visible_modules.each do |menu_item|
|
9
9
|
%li.nav-item.d-none.d-sm-inline-block
|
10
10
|
= link_to menu_item.text, menu_item.href, class: 'nav-link'
|
11
11
|
/ Right navbar links
|
@@ -113,7 +113,7 @@
|
|
113
113
|
%li.user-footer
|
114
114
|
= link_to user_path(current_user), class: 'btn btn-default btn-flat' do
|
115
115
|
Profile
|
116
|
-
= link_to
|
116
|
+
= link_to Olivander::CurrentContext.application_context.sign_out_path, method: :delete, class: 'btn btn-default btn-flat float-right' do
|
117
117
|
Sign out
|
118
118
|
%li.nav-item
|
119
119
|
%a.nav-link{title: 'Full Screen Mode', "data-widget" => "fullscreen", :href => "#", :role => "button"}
|
@@ -2,7 +2,7 @@
|
|
2
2
|
%aside.main-sidebar.sidebar-dark-primary.elevation-4{ data: { controller: 'left-nav' }}
|
3
3
|
/ Brand Logo
|
4
4
|
%a.brand-link{ href: "/", class: sidebar_background_class }
|
5
|
-
%img.brand-image.img-circle.elevation-3{:alt =>
|
5
|
+
%img.brand-image.img-circle.elevation-3{:alt => Olivander::CurrentContext.application_context.logo.alt, :src => Olivander::CurrentContext.application_context.logo.url, :style => "opacity: .8"}/
|
6
6
|
%span.brand-text.font-weight-light= sidebar_context_name
|
7
7
|
/ Sidebar
|
8
8
|
.sidebar
|
@@ -16,7 +16,7 @@
|
|
16
16
|
/ Sidebar Menu
|
17
17
|
%nav.mt-2
|
18
18
|
%ul.nav.nav-pills.nav-sidebar.nav-compact.flex-column{"data-accordion" => "false", "data-widget" => "treeview", :role => "menu"}
|
19
|
-
-
|
19
|
+
- Olivander::CurrentContext.application_context.menu_items.each do |menu_item|
|
20
20
|
= render Olivander::Components::MenuItemComponent.new(menu_item)
|
21
21
|
|
22
22
|
|
@@ -4,7 +4,7 @@
|
|
4
4
|
%body.hold-transition.login-page
|
5
5
|
.login-box
|
6
6
|
-# .login-logo
|
7
|
-
-# %img.brand-image.img-circle.elevation-3{:alt =>
|
7
|
+
-# %img.brand-image.img-circle.elevation-3{:alt => Olivander::CurrentContext.application_context.logo.alt, :src => Olivander::CurrentContext.application_context.logo.url, :style => "opacity: .8"}
|
8
8
|
.card
|
9
9
|
.card-header.text-center{ class: sidebar_background_class }
|
10
10
|
%a.h1{ href: '/' }
|
@@ -1,6 +1,5 @@
|
|
1
1
|
!!!
|
2
2
|
%html
|
3
|
-
- @context ||= Olivander::ApplicationContext.default
|
4
3
|
= render partial: 'layouts/olivander/adminlte/head'
|
5
4
|
- sidebar_collapse = cookies['lte.pushmenu.collapsed'] == 'true' ? 'sidebar-collapse' : ''
|
6
5
|
%body.hold-transition.sidebar-mini.layout-fixed{ class: sidebar_collapse }
|
@@ -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.
|
80
|
-
|
81
|
-
|
82
|
-
b.use :
|
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
|
-
|
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,18 +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
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
self.menu_items = menu_items
|
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] || []
|
11
|
+
begin
|
12
|
+
self.route_builder = RouteBuilder.new
|
13
|
+
rescue NameError
|
14
|
+
self.route_builder = OpenStruct.new(resources: [])
|
15
|
+
end
|
17
16
|
end
|
18
17
|
|
19
18
|
def visible_modules
|
@@ -36,19 +35,28 @@ module Olivander
|
|
36
35
|
class Logo
|
37
36
|
attr_accessor :url, :alt
|
38
37
|
|
39
|
-
def initialize(
|
40
|
-
self.url = url
|
41
|
-
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'
|
42
41
|
end
|
43
42
|
end
|
44
43
|
|
45
44
|
class Company
|
46
45
|
attr_accessor :name, :url
|
47
46
|
|
48
|
-
def initialize(
|
49
|
-
self.url = url
|
50
|
-
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'
|
51
50
|
end
|
52
51
|
end
|
53
52
|
end
|
53
|
+
|
54
|
+
class CurrentContext < ActiveSupport::CurrentAttributes
|
55
|
+
attribute :application_context
|
56
|
+
attribute :user, :ability
|
57
|
+
|
58
|
+
def application_context
|
59
|
+
@application_context ||= ::Olivander::ApplicationContext.new
|
60
|
+
end
|
61
|
+
end
|
54
62
|
end
|
data/lib/olivander/version.rb
CHANGED
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.
|
4
|
+
version: 0.2.0.2
|
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-
|
11
|
+
date: 2024-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chartkick
|
@@ -208,6 +208,7 @@ files:
|
|
208
208
|
- app/assets/javascripts/adminlte/select2_defaults.coffee
|
209
209
|
- app/assets/javascripts/controllers/datatable_expandable_chart_controller.js
|
210
210
|
- app/assets/javascripts/controllers/datatable_index_charts_controller.js
|
211
|
+
- app/assets/javascripts/controllers/input_control_association_controller.js
|
211
212
|
- app/assets/javascripts/controllers/turbo_flash_controller.js
|
212
213
|
- app/assets/javascripts/olivander/flash_toast.js
|
213
214
|
- app/assets/stylesheets/adminlte.css
|
@@ -228,15 +229,17 @@ files:
|
|
228
229
|
- app/components/olivander/components/table_portlet_component.html.haml
|
229
230
|
- app/components/olivander/components/table_portlet_component.rb
|
230
231
|
- app/components/olivander/components/table_portlet_component/table_component.html.haml
|
232
|
+
- app/controllers/concerns/olivander/resources/application_record.rb
|
231
233
|
- app/controllers/concerns/olivander/resources/auto_form_attributes.rb
|
234
|
+
- app/controllers/concerns/olivander/resources/crud_controller.rb
|
232
235
|
- app/controllers/concerns/olivander/resources/route_builder.rb
|
233
236
|
- app/controllers/olivander/application_controller.rb
|
234
237
|
- app/datatables/olivander/datatable.rb
|
235
238
|
- app/helpers/olivander/application_helper.rb
|
239
|
+
- app/inputs/custom_form_builder.rb
|
236
240
|
- app/inputs/date_time_input.rb
|
237
241
|
- app/jobs/olivander/application_job.rb
|
238
242
|
- app/mailers/olivander/application_mailer.rb
|
239
|
-
- app/models/olivander/application_record.rb
|
240
243
|
- app/views/application/_form.html.haml
|
241
244
|
- app/views/application/_resource_form_actions.html.haml
|
242
245
|
- 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
|