five-two-nw-olivander 0.1.2.2 → 0.1.2.3

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: 44fe284f2bfe724fd9afc389fe29459b92d7358bd2db4bbcc834c575b4defb89
4
- data.tar.gz: 19de553ddc1641dea2af0b12e41a9c9c4459470972205227d106d6cc61f5660e
3
+ metadata.gz: 597764e454652e4a42b1d81c7d63db17f9495a662886fd9184c7fc3790d16c75
4
+ data.tar.gz: faa979538cb5fa01390a65e0378054b3f916b3f3630ac45e586ff64fb43e9ffa
5
5
  SHA512:
6
- metadata.gz: 29b8d4a75d6680a5283562bcd52e746a74c21cff1b9f0ed6982d6132c05cafc28659343a5f9ed6d18de437c36bb08a9966ba21cf6cd873c98028137785b59358
7
- data.tar.gz: b698a84298b468c808c630332a19e90f8061b4f8ef232324a8c890e15fa5c0cd5c6d2adbc0408085dcfce1e2334a69d98a811f4ab8f4d405eda5eea55392ceb6
6
+ metadata.gz: b1d0847e4694082bcbf22f3717f4ea551f1144697b51e809539118402f347e46158767a8fdca8eab49b1262dde97e09ad964f8722b0d3701cfbfe3789478da34
7
+ data.tar.gz: 92df52efda623339deb45a35ad86c5a52e0205ba5eb49e71aa70d5683eb2df079825531407f58634c0970c0a6802b8c62081e6c910fdedd494dec4a88fbd90a6
@@ -0,0 +1,13 @@
1
+ module Olivander
2
+ module Resources
3
+ module AutoFormAttributes
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ def auto_form_attributes
8
+ attributes.keys - ['updated_at', 'created_at', 'deleted_at']
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,129 @@
1
+ module Olivander
2
+ module Resources
3
+ class ResourceAction
4
+ attr_accessor :sym, :action, :verb, :confirm, :turbo_frame, :collection, :controller, :crud_action, :show_in_form, :show_in_datatable, :no_route
5
+
6
+ def initialize(sym, action: nil, controller: nil, verb: :get, confirm: false, turbo_frame: nil, collection: false, crud_action: false,
7
+ show_in_form: true, show_in_datatable: true, no_route: false)
8
+ self.sym = sym
9
+ self.action = action || sym
10
+ self.controller = controller
11
+ self.verb = verb
12
+ self.confirm = confirm
13
+ self.turbo_frame = turbo_frame
14
+ self.collection = collection
15
+ self.crud_action = crud_action
16
+ self.show_in_form = show_in_form
17
+ self.show_in_datatable = show_in_datatable
18
+ self.no_route = no_route
19
+ end
20
+ end
21
+
22
+ class RoutedResource
23
+ attr_accessor :model, :actions
24
+
25
+ def initialize(model, crud_actions)
26
+ self.model = model
27
+ self.actions = []
28
+ crud_actions.each do |ca|
29
+ actions << ResourceAction.new(ca, controller: model, crud_action: true)
30
+ end
31
+ end
32
+
33
+ def crud_actions
34
+ actions.select{ |x| x.crud_action }
35
+ end
36
+
37
+ def additional_actions
38
+ actions.select{ |x| !x.crud_action }
39
+ end
40
+
41
+ def member_actions
42
+ additional_actions.select{ |x| !x.collection }
43
+ end
44
+
45
+ def collection_actions
46
+ additional_actions.select{ |x| x.collection }
47
+ end
48
+
49
+ def datatable_bulk_actions
50
+ collection_actions.select{ |x| x.show_in_datatable }
51
+ end
52
+
53
+ def unpersisted_crud_actions
54
+ allowed = %i[index new]
55
+ crud_actions.select{ |x| allowed.include?(x.sym) }
56
+ end
57
+
58
+ def persisted_crud_actions
59
+ allowed = %i[show edit destroy]
60
+ crud_actions.select{ |x| allowed.include?(x.sym) }
61
+ end
62
+ end
63
+
64
+ module RouteBuilder
65
+ extend ActiveSupport::Concern
66
+
67
+ DEFAULT_CRUD_ACTIONS = %i[index new create show edit update destroy]
68
+
69
+ included do
70
+ class_attribute :resources, default: {}
71
+ class_attribute :current_resource
72
+ end
73
+
74
+ class_methods do
75
+ def resource(model, only: DEFAULT_CRUD_ACTIONS, except: [], &block)
76
+ self.current_resource = RoutedResource.new(model, DEFAULT_CRUD_ACTIONS & (only - except))
77
+ yield if block_given?
78
+ resources[model] = current_resource
79
+ self.current_resource = nil
80
+ end
81
+
82
+ def action(sym, verb: :get, confirm: false, turbo_frame: nil, collection: false, show_in_datatable: true, show_in_form: true, no_route: false, controller: nil, action: nil)
83
+ raise 'Must be invoked in a resource block' unless current_resource.present?
84
+
85
+ controller ||= current_resource.model
86
+ current_resource.actions << ResourceAction.new(
87
+ sym, action: action, controller: controller, verb: verb, confirm: confirm, turbo_frame: turbo_frame, collection: collection,
88
+ show_in_datatable: show_in_datatable, show_in_form: show_in_form, no_route: no_route
89
+ )
90
+ end
91
+
92
+ def build_routes(mapper)
93
+ build_resource_routes(mapper)
94
+ end
95
+
96
+ def build_resource_routes(mapper)
97
+ resources.keys.each do |k|
98
+ r = resources[k]
99
+ mapper.resources r.model, only: r.crud_actions.map{ |ca| ca.action } do
100
+ mapper.member do
101
+ r.member_actions.each do |ma|
102
+ next if ma.no_route
103
+ if ma.confirm
104
+ mapper.get ma.action, action: "confirm_#{ma.action}"
105
+ mapper.post ma.action
106
+ else
107
+ mapper.send(ma.verb, ma.action)
108
+ end
109
+ end
110
+ end
111
+
112
+ mapper.collection do
113
+ r.collection_actions.each do |ba|
114
+ next if ba.no_route
115
+ if ba.confirm
116
+ mapper.get ba.action, action: "confirm_#{ba.action}"
117
+ mapper.post ba.action
118
+ else
119
+ mapper.send(ma.verb, ba.action)
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -16,5 +16,22 @@ module Olivander
16
16
  def user_image_path(user)
17
17
  "avatar#{SecureRandom.random_number(4)}.png"
18
18
  end
19
+
20
+ def authorized_resource_actions(resource, for_action: :show)
21
+ plural_name = resource.is_a?(Class) ? resource.table_name : resource.class.table_name
22
+ routed_resource = @context.route_builder.resources[plural_name.to_sym]
23
+ actions = resource.is_a?(Class) ?
24
+ (routed_resource.unpersisted_crud_actions | routed_resource.collection_actions) :
25
+ (resource.persisted? ? (routed_resource.persisted_crud_actions | routed_resource.member_actions): [])
26
+ actions.reject{ |a| a.sym == for_action }
27
+ end
28
+
29
+ def resource_form_actions(resource, for_action: :show)
30
+ [].tap do |output|
31
+ authorized_resource_actions(resource, for_action: for_action).select{ |x| x.show_in_form }.each do |a|
32
+ output << link_to(a.sym, {controller: a.controller, action: a.action}, method: a.verb, class: 'btn btn-primary', data: { turbo: true })
33
+ end
34
+ end.join('&nbsp;').html_safe
35
+ end
19
36
  end
20
37
  end
@@ -0,0 +1,17 @@
1
+ - read_only = action_name != 'edit'
2
+ = simple_form_for(@resource) do |f|
3
+ .card
4
+ .card-header
5
+ .card-tools
6
+ = resource_form_actions(@resource, for_action: action_name.to_sym)
7
+ .card-body
8
+ =f.error_notification
9
+ =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
14
+ .card-footer.text-right
15
+ = link_to 'Cancel', @_effective_resource.action_path(:index), class: 'btn btn-secondary'
16
+ - unless read_only
17
+ = f.button :submit, class: 'btn btn-primary'
@@ -3,9 +3,5 @@
3
3
 
4
4
  - if @resource
5
5
  .row
6
- .col-8
7
- %h1= @page_title
8
- .col-4.text-right
9
- = render_resource_buttons(@resource, edit: false)
10
-
11
- = render_resource_form(@resource)
6
+ .col-12
7
+ = render_resource_form(@resource)
@@ -4,7 +4,9 @@
4
4
  .col-12
5
5
  .card
6
6
  .card-header
7
- %h1= @page_title
7
+ %h3.card-title= @page_title
8
+ .card-tools
9
+ = resource_form_actions(resource.klass, for_action: :index)
8
10
  .card-body
9
11
  - if @datatable
10
12
  = render_datatable(@datatable)
@@ -19,6 +21,5 @@
19
21
  %p effective_resources index view is not sure what to render.
20
22
  %p Define an @datatable, @#{resource.try(:plural_name) || 'a plural'}, or @#{resource.try(:name) || 'a singular'}.
21
23
  %p or include Effective::CrudController in your controller
22
- .card-footer
23
- = render_resource_buttons(resource.klass, (action ||= :index) => false)
24
+ -# .card-footer
24
25
 
@@ -2,10 +2,4 @@
2
2
  - @resource = instance_variable_get('@' + resource.name) if resource.name
3
3
 
4
4
  - if @resource
5
- .row
6
- .col-8
7
- %h1= @page_title
8
- .col-4.text-right
9
- = render_resource_buttons(@resource)
10
-
11
5
  = render_resource_form(@resource)
@@ -3,12 +3,6 @@
3
3
 
4
4
  - if @resource
5
5
  .row
6
- .col-8
7
- %h1= @page_title
8
- .col-4.text-right
9
- = render_resource_buttons(@resource, show: false)
6
+ .col-12
7
+ = render_resource_form(@resource)
10
8
 
11
- = render_resource_partial(@resource)
12
-
13
- .form-actions
14
- = link_to 'Continue', (resource.action_path(:index) || root_path), class: 'btn btn-primary'
@@ -0,0 +1,3 @@
1
+ = dropdown(variation: :dropleft, btn_class: btn_class) do
2
+ - authorized_resource_actions(resource, for_action: action_name).select{ |x| x.show_in_datatable }.each do |a|
3
+ = dropdown_link_to a.sym, { controller: a.controller, action: a.action, id: resource.id }
@@ -8,4 +8,4 @@
8
8
  = javascript_include_tag "https://www.gstatic.com/charts/loader.js"
9
9
  = stylesheet_link_tag "adminlte", "data-turbo-track": "reload"
10
10
  = javascript_include_tag "adminlte", "data-turbo-track": "reload"
11
- -# = javascript_importmap_tags
11
+ = javascript_importmap_tags
@@ -24,3 +24,38 @@
24
24
  %ul.nav.nav-pills.nav-sidebar.nav-compact.flex-column{"data-accordion" => "false", "data-widget" => "treeview", :role => "menu"}
25
25
  - @context.menu_items.each do |menu_item|
26
26
  = render Olivander::Components::MenuItemComponent.new(menu_item)
27
+
28
+
29
+ :javascript
30
+ $(document).ready(function(){
31
+ function getUrl() {
32
+ const reg = /\/new|\/[0-9]+[\/edit]*/,
33
+ url = "" + window.location;
34
+ return url.replace(reg, '');
35
+ }
36
+ const url = getUrl();
37
+
38
+ $('ul.nav-sidebar a').filter(function() {
39
+ return this.href == url;
40
+ }).addClass('active');
41
+
42
+ $('ul.nav-sidebar a').filter(function() {
43
+ return this.href == url;
44
+ }).parent().addClass('active');
45
+
46
+ $('ul.nav-treeview a').filter(function() {
47
+ return this.href == url;
48
+ }).parentsUntil(".sidebar-menu > .nav-treeview").addClass('menu-open');
49
+
50
+ $('ul.nav-treeview a').filter(function() {
51
+ return this.href == url;
52
+ }).addClass('active');
53
+
54
+ $('li.has-treeview a').filter(function() {
55
+ return this.href == url;
56
+ }).addClass('active');
57
+
58
+ $('ul.nav-treeview a').filter(function() {
59
+ return this.href == url;
60
+ }).parentsUntil(".sidebar-menu > .nav-treeview").children(0).addClass('active');
61
+ });
@@ -1,6 +1,6 @@
1
1
  module Olivander
2
2
  class ApplicationContext
3
- attr_accessor :name, :logo, :company, :menu_items
3
+ attr_accessor :name, :logo, :company, :menu_items, :route_builder
4
4
 
5
5
  def self.default
6
6
  ctx = ApplicationContext.new
@@ -1,3 +1,3 @@
1
1
  module Olivander
2
- VERSION = "0.1.2.2"
2
+ VERSION = "0.1.2.3"
3
3
  end
@@ -0,0 +1,8 @@
1
+ = simple_form_for(@resource) do |f|
2
+ =f.error_notification}
3
+ =f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present?}
4
+ .form-inputs
5
+ - attributes.each do |attribute|
6
+ = f.send(attribute.reference? ? :association : :input, attribute.name)
7
+ .form-actions
8
+ = f.button :submit
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.2
4
+ version: 0.1.2.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: 2023-07-03 00:00:00.000000000 Z
11
+ date: 2023-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chartkick
@@ -171,21 +171,21 @@ files:
171
171
  - app/assets/stylesheets/olivander/application.css
172
172
  - app/components/olivander/components/menu_item_component.html.haml
173
173
  - app/components/olivander/components/menu_item_component.rb
174
+ - app/controllers/concerns/olivander/resources/auto_form_attributes.rb
175
+ - app/controllers/concerns/olivander/resources/route_builder.rb
174
176
  - app/controllers/olivander/application_controller.rb
175
- - app/controllers/olivander/resources/crud_chain.rb
176
- - app/controllers/olivander/resources/crud_controller.rb
177
- - app/controllers/olivander/resources/default_crud_chain.rb
178
- - app/controllers/olivander/test_controller.rb
179
177
  - app/datatables/olivander/datatable.rb
180
178
  - app/datatables/test_datatable.rb
181
179
  - app/helpers/olivander/application_helper.rb
182
180
  - app/jobs/olivander/application_job.rb
183
181
  - app/mailers/olivander/application_mailer.rb
184
182
  - app/models/olivander/application_record.rb
183
+ - app/views/application/_form.html.haml
185
184
  - app/views/application/edit.html.haml
186
185
  - app/views/application/index.html.haml
187
186
  - app/views/application/new.html.haml
188
187
  - app/views/application/show.html.haml
188
+ - app/views/effective/resource/_actions_dropleft.html.haml
189
189
  - app/views/layouts/olivander/adminlte/_content.html.haml
190
190
  - app/views/layouts/olivander/adminlte/_content_kanban.html.haml
191
191
  - app/views/layouts/olivander/adminlte/_control_sidebar.html.haml
@@ -210,7 +210,7 @@ files:
210
210
  - lib/olivander/menus/menu_item.rb
211
211
  - lib/olivander/version.rb
212
212
  - lib/tasks/olivander_tasks.rake
213
- - lib/templates/erb/scaffold/_form.html.erb
213
+ - lib/templates/erb/scaffold/_form.html.haml
214
214
  homepage: https://rubygems.org/gems/olivander
215
215
  licenses:
216
216
  - MIT
@@ -1,119 +0,0 @@
1
- module Olivander
2
- module Resources
3
- class CrudChain
4
- attr_accessor :controller
5
-
6
- def initialize(controller)
7
- @controller = controller
8
- end
9
-
10
- def links
11
- @links ||= {
12
- authorize_action: nil,
13
- before_load: nil, load_resource: nil, after_load: nil,
14
- authorize_resource: nil,
15
- before_assign: nil, assign: nil, after_assign: nil,
16
- update_if: nil,
17
- before_update: nil, update: nil, after_update: nil,
18
- update_success: nil, update_failure: nil,
19
- render_success: nil, render_failure: nil
20
- }
21
- end
22
-
23
- def on(chain_link, &block)
24
- raise "Invalid Link: #{chain_link}" unless links.keys.include?(chain_link)
25
-
26
- links[chain_link] = block
27
- self
28
- end
29
-
30
- def skip_load
31
- clear_keys(%i[before_load load_resource after_load])
32
- self
33
- end
34
-
35
- def skip_assign
36
- clear_keys(%i[before_assign assign after_assign])
37
- self
38
- end
39
-
40
- def skip_update
41
- update_if { false }
42
- self
43
- end
44
-
45
- def skip_render
46
- clear_keys(%i[render_success render_failure])
47
- self
48
- end
49
-
50
- def execute
51
- execute_link_keys(%i[authorize_action before_load load_resource after_load authorize_resource before_assign assign after_assign])
52
- success = perform_update
53
- # we may not do any update - in which case we assume success
54
- success = true if success.nil?
55
- execute_link_key(success ? :render_success : :render_failure)
56
- success
57
- end
58
-
59
- # def self.test
60
- # CrudChain.new('string')
61
- # .before_load { puts "we did a before load from within this action: #{self}" }
62
- # .before_update { puts "we are doing a before_update on a controller named: #{self.class.name}" }
63
- # .execute
64
- # end
65
-
66
- def clear_keys(keys)
67
- keys.each { |k| clear_key(k) }
68
- end
69
-
70
- def clear_keys_except(keys)
71
- (links.keys - keys).each { |k| clear_key(k) }
72
- end
73
-
74
- def clear_key(key)
75
- links[key] = nil
76
- end
77
-
78
- private
79
-
80
- def perform_update
81
- perform_update = execute_link_key(:update_if)
82
- perform_update = true if perform_update.nil?
83
- return false unless perform_update
84
-
85
- execute_link_key(:before_update)
86
- success = execute_link_key(:update)
87
- execute_link_key(:after_update)
88
- execute_link_key(success ? :update_success : :update_failure)
89
- success
90
- end
91
-
92
- def execute_link_keys(keys)
93
- keys.each do |k|
94
- execute_link_key(k)
95
- end
96
- end
97
-
98
- def execute_link_key(key)
99
- block = links[key]
100
- return if block.nil?
101
-
102
- @controller.instance_exec(&block)
103
- end
104
-
105
- def respond_to_missing?(method_name, _include_private = false)
106
- links.keys.include?(method_name.to_sym)
107
- end
108
-
109
- # syntax sugar to allow direct assignment of a chain link
110
- def method_missing(m, *args, &block)
111
- if respond_to_missing?(m)
112
- send(:on, m, &block)
113
- else
114
- super
115
- end
116
- end
117
- end
118
- end
119
- end
@@ -1,55 +0,0 @@
1
- module Olivander
2
- module Resources
3
- module CrudController
4
- def index
5
- execute_crud_chain(crud_action: :index)
6
- end
7
-
8
- def new
9
- execute_crud_chain(crud_action: :new)
10
- end
11
-
12
- def create
13
- execute_crud_chain(crud_action: :create)
14
- end
15
-
16
- def show
17
- execute_crud_chain(crud_action: :show)
18
- end
19
-
20
- def edit
21
- execute_crud_chain(crud_action: :edit)
22
- end
23
-
24
- def update
25
- execute_crud_chain(crud_action: :update)
26
- end
27
-
28
- def destroy
29
- execute_crud_chain(crud_action: :destroy)
30
- end
31
-
32
- def execute_crud_chain(crud_action: action_name, only: [], skip: [], &block)
33
- chain = default_crud_chain(crud_action)
34
- chain.clear_keys_except(only) if only.size.positive?
35
- chain.clear_keys(skip) if skip.size.positive?
36
- yield(chain) if block_given?
37
- chain.execute
38
- end
39
-
40
- def default_crud_chain(crud_action = '')
41
- chain = Olivander::Resources::CrudChain.new(self)
42
- chain.links.keys.each do |k|
43
- method_name = "crud_chain_#{crud_action}_#{k}"
44
- method_name = "crud_chain_#{k}" unless respond_to?(method_name)
45
- next unless respond_to?(method_name)
46
-
47
- chain.on(k) do
48
- send(method_name)
49
- end
50
- end
51
- chain
52
- end
53
- end
54
- end
55
- end
@@ -1,48 +0,0 @@
1
- module Olivander
2
- module Resources
3
- module DefaultCrudChain
4
- def crud_chain_index_authorize_action
5
- puts 'default crud chain: index_authorize_action'
6
- end
7
-
8
- def crud_chain_index_load_resource
9
- puts 'default crud chain: index_load_resource'
10
- end
11
-
12
- def crud_chain_load_resource
13
- puts 'default crud chain: load_resource'
14
- end
15
-
16
- def crud_chain_authorize_resource
17
- raise 'Unauthorized' unless true
18
- puts 'default crud chain: authorize_resource'
19
- end
20
-
21
- def crud_chain_assign
22
- puts 'default crud chain: assign'
23
- end
24
-
25
- def crud_chain_update_if
26
- puts 'default crud chain: update_if'
27
- return true if %w[create update destroy].include?(action_name)
28
- return false if %w[index new show edit].include?(action_name)
29
- return false if request.method == 'GET'
30
-
31
- true
32
- end
33
-
34
- def crud_chain_update
35
- puts 'default crud chain: update'
36
- true
37
- end
38
-
39
- def crud_chain_render_success
40
- puts 'default crud chain: render_success'
41
- end
42
-
43
- def crud_chain_render_failure
44
- puts 'default crud chain: render_failure'
45
- end
46
- end
47
- end
48
- end
@@ -1,35 +0,0 @@
1
- module Olivander
2
- class TestController < ApplicationController
3
- include Olivander::Resources::CrudController
4
- include Olivander::Resources::DefaultCrudChain
5
-
6
- def index
7
- execute_crud_chain(crud_action: :index) do |c|
8
- c.authorize_resource { puts 'block: authorize_resource'; true }
9
- .update { puts 'block: update'; true }
10
- .before_assign { puts 'block: before assign' }
11
- .after_assign { puts 'block: after assign' }
12
- end
13
- end
14
-
15
- # def crud_chain_update
16
- # puts 'controller: update'
17
- # end
18
-
19
- # def crud_chain_index_update
20
- # puts 'controller: index_update'
21
- # end
22
-
23
- # def crud_chain_before_load
24
- # puts 'controller: before_load'
25
- # end
26
-
27
- # def crud_chain_after_update
28
- # puts 'controller: after_update'
29
- # end
30
-
31
- # def crud_chain_index_after_update
32
- # puts 'controller: index_after_update'
33
- # end
34
- end
35
- end
@@ -1,15 +0,0 @@
1
- <%# frozen_string_literal: true %>
2
- <%%= simple_form_for(@<%= singular_table_name %>) do |f| %>
3
- <%%= f.error_notification %>
4
- <%%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
5
-
6
- <div class="form-inputs">
7
- <%- attributes.each do |attribute| -%>
8
- <%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %>
9
- <%- end -%>
10
- </div>
11
-
12
- <div class="form-actions">
13
- <%%= f.button :submit %>
14
- </div>
15
- <%% end %>