nitro_rails 0.1.0 → 0.1.1

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.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +18 -0
  3. data/app/assets/audio/mousetap.mp3 +0 -0
  4. data/app/assets/config/nitro_rails_manifest.js +2 -0
  5. data/app/assets/javascript/nitro_rails/application.js +4 -0
  6. data/app/assets/javascript/nitro_rails/controllers/application.js +9 -0
  7. data/app/assets/javascript/nitro_rails/controllers/audio_controller.js +16 -0
  8. data/app/assets/javascript/nitro_rails/controllers/clock_controller.js +21 -0
  9. data/app/assets/javascript/nitro_rails/controllers/editable_text_controller.js +61 -0
  10. data/app/assets/javascript/nitro_rails/controllers/index.js +21 -0
  11. data/app/assets/javascript/nitro_rails/controllers/nitro_collection_controller.js +127 -0
  12. data/app/assets/javascript/nitro_rails/controllers/nitro_controller.js +35 -0
  13. data/app/assets/javascript/nitro_rails/controllers/nitro_form_controller.js +81 -0
  14. data/app/assets/javascript/nitro_rails/controllers/panel_controller.js +70 -0
  15. data/app/assets/javascript/nitro_rails/controllers/panel_manager_controller.js +89 -0
  16. data/app/assets/javascript/nitro_rails/controllers/tabs_controller.js +81 -0
  17. data/app/assets/javascript/nitro_rails/controllers/time_zone_controller.js +47 -0
  18. data/app/assets/javascript/nitro_rails/controllers/togglable_checkbox_controller.js +9 -0
  19. data/app/assets/javascript/nitro_rails/helpers/device_info_helper.js +99 -0
  20. data/app/assets/javascript/nitro_rails/helpers/screen_info_helper.js +20 -0
  21. data/app/assets/javascript/nitro_rails/turbo_streams/clear_errors.js +22 -0
  22. data/app/assets/javascript/nitro_rails/turbo_streams/focus.js +8 -0
  23. data/app/assets/javascript/nitro_rails/turbo_streams/index.js +8 -0
  24. data/app/assets/javascript/nitro_rails/turbo_streams/insert.js +10 -0
  25. data/app/assets/javascript/nitro_rails/turbo_streams/redirect.js +10 -0
  26. data/app/assets/javascript/nitro_rails/turbo_streams/refresh_frame.js +9 -0
  27. data/app/assets/javascript/nitro_rails/turbo_streams/render_errors.js +26 -0
  28. data/app/assets/javascript/nitro_rails/turbo_streams/toggle_checkbox.js +9 -0
  29. data/app/assets/javascript/nitro_rails/turbo_streams/toggle_class.js +14 -0
  30. data/app/assets/stylesheets/nitro_rails/__reset.css +25 -0
  31. data/app/assets/stylesheets/nitro_rails/_base/_color.css +24 -0
  32. data/app/assets/stylesheets/nitro_rails/_base/_font.css +35 -0
  33. data/app/assets/stylesheets/nitro_rails/_base/_format.css +38 -0
  34. data/app/assets/stylesheets/nitro_rails/_base/_grayscale.css +79 -0
  35. data/app/assets/stylesheets/nitro_rails/_base/_utility.css +34 -0
  36. data/app/assets/stylesheets/nitro_rails/application.css +23 -0
  37. data/app/assets/stylesheets/nitro_rails/modules/action-navigation.css +24 -0
  38. data/app/assets/stylesheets/nitro_rails/modules/alert.css +31 -0
  39. data/app/assets/stylesheets/nitro_rails/modules/btn.css +57 -0
  40. data/app/assets/stylesheets/nitro_rails/modules/checkbox.css +42 -0
  41. data/app/assets/stylesheets/nitro_rails/modules/clickable.css +9 -0
  42. data/app/assets/stylesheets/nitro_rails/modules/clock.css +0 -0
  43. data/app/assets/stylesheets/nitro_rails/modules/editable-text.css +45 -0
  44. data/app/assets/stylesheets/nitro_rails/modules/forms.css +108 -0
  45. data/app/assets/stylesheets/nitro_rails/modules/hover-reveal.css +11 -0
  46. data/app/assets/stylesheets/nitro_rails/modules/inline-svg.css +14 -0
  47. data/app/assets/stylesheets/nitro_rails/modules/list.css +29 -0
  48. data/app/assets/stylesheets/nitro_rails/modules/main-navigation.css +20 -0
  49. data/app/assets/stylesheets/nitro_rails/modules/nitro-checkbox.css +42 -0
  50. data/app/assets/stylesheets/nitro_rails/modules/resource-collection.css +12 -0
  51. data/app/assets/stylesheets/nitro_rails/modules/search-bar.css +36 -0
  52. data/app/assets/stylesheets/nitro_rails/modules/settings.css +33 -0
  53. data/app/assets/stylesheets/nitro_rails/modules/tabs.css +38 -0
  54. data/app/assets/stylesheets/nitro_rails/modules/toggle-switch.css +60 -0
  55. data/app/assets/stylesheets/nitro_rails/panels/bound-card-dropdown-panel.css +0 -0
  56. data/app/assets/stylesheets/nitro_rails/panels/card-panel.css +0 -0
  57. data/app/assets/stylesheets/nitro_rails/panels/embedded-panel.css +31 -0
  58. data/app/assets/stylesheets/nitro_rails/panels/panel-display.css +111 -0
  59. data/app/assets/stylesheets/nitro_rails/panels/popup-panel.css +123 -0
  60. data/app/assets/stylesheets/nitro_rails/panels/side-panel.css +0 -0
  61. data/app/controllers/nitro_rails/sequence_controller.rb +64 -0
  62. data/app/helpers/nitro_rails/application_helper.rb +42 -1
  63. data/app/helpers/nitro_rails/color_helper.rb +23 -0
  64. data/app/helpers/nitro_rails/components_helper.rb +49 -0
  65. data/app/helpers/nitro_rails/inline_edit_helper.rb +48 -0
  66. data/app/helpers/nitro_rails/nitro_action_helper.rb +178 -0
  67. data/app/helpers/nitro_rails/nitro_collection_helper.rb +87 -0
  68. data/app/helpers/nitro_rails/nitro_edit_helper.rb +15 -0
  69. data/app/helpers/nitro_rails/nitro_form_helper.rb +104 -0
  70. data/app/helpers/nitro_rails/nitro_options_helper.rb +78 -0
  71. data/app/helpers/nitro_rails/nitro_tag_helper.rb +183 -0
  72. data/app/helpers/nitro_rails/panel_helper.rb +65 -0
  73. data/app/helpers/nitro_rails/resource_collection_helper.rb +66 -0
  74. data/app/helpers/nitro_rails/tabs_helper.rb +51 -0
  75. data/app/helpers/nitro_rails/turbo_stream_helper.rb +46 -0
  76. data/app/lib/nitro_rails/local_time.rb +51 -0
  77. data/app/lib/nitro_rails/performable_routes.rb +24 -0
  78. data/app/lib/nitro_rails/resource_collection.rb +183 -0
  79. data/app/lib/nitro_rails/sequential_routes.rb +36 -0
  80. data/app/lib/nitro_rails/time_interval.rb +88 -0
  81. data/app/lib/nitro_rails/time_string.rb +22 -0
  82. data/app/models/nitro_rails/broadcast.rb +76 -0
  83. data/app/models/nitro_rails/broadcastable_model.rb +91 -0
  84. data/app/models/nitro_rails/broadcastable_record.rb +118 -0
  85. data/app/models/nitro_rails/default_broadcasts.rb +149 -0
  86. data/app/models/nitro_rails/record.rb +50 -0
  87. data/app/pseudocode/nitro.html.erb +18 -0
  88. data/app/view_components/nitro_rails/nitro_collection/batch_selectable.rb +24 -0
  89. data/app/view_components/nitro_rails/nitro_collection.rb +66 -0
  90. data/app/view_components/nitro_rails/view_component.rb +9 -0
  91. data/app/views/layouts/nitro_rails/application.html.erb +3 -5
  92. data/app/views/nitro_rails/_editable_text.html.erb +32 -0
  93. data/app/views/nitro_rails/_nitro_checkbox.html.erb +5 -0
  94. data/app/views/nitro_rails/_nitro_form.html.erb +10 -0
  95. data/app/views/nitro_rails/_panel_frame_tag.html.erb +8 -0
  96. data/app/views/nitro_rails/_panel_template.html.erb +40 -0
  97. data/app/views/nitro_rails/_togglable_checkbox.html.erb +16 -0
  98. data/config/importmap.rb +1 -0
  99. data/config/initializers/date_formatters.rb +9 -0
  100. data/lib/nitro_rails/engine.rb +25 -0
  101. data/lib/nitro_rails/version.rb +1 -1
  102. metadata +165 -3
  103. data/app/models/nitro_rails/application_record.rb +0 -5
@@ -0,0 +1,123 @@
1
+ .panel-container.popup .panel-display {
2
+ width: 500px;
3
+ z-index: 100;
4
+ opacity: 1;
5
+ margin: 0 auto;
6
+ right: initial;
7
+ top: initial;
8
+ display: block;
9
+ height: 80vh;
10
+ max-height: 800px;
11
+ animation: slideUp ease-in-out 200ms 1 forwards;
12
+ }
13
+
14
+ @keyframes slideUp {
15
+ 0% {
16
+ transform: translateY(8%);
17
+ opacity: 0;
18
+ }
19
+ 100% {
20
+ transform: translateY(0);
21
+ opacity: 1;
22
+ }
23
+ }
24
+
25
+
26
+ .panel-container.popup .panel-display .content {
27
+ transition: background-color 1s;
28
+ }
29
+
30
+
31
+ .panel-container.popup .panel-display .content {
32
+ padding: 30px;
33
+ }
34
+
35
+ .panel-container.popup.active .panel-background {
36
+ background-color: rgba(0, 0, 0, 0.5);
37
+ /* add blur */
38
+ backdrop-filter: blur(10px);
39
+ -webkit-backdrop-filter: blur(10px);
40
+ position: fixed;
41
+ top: 0;
42
+ left: 0;
43
+ right: 0;
44
+ bottom: 0;
45
+ overflow: hidden;
46
+ z-index: 10000;
47
+ align-items: center;
48
+ justify-content: center;
49
+ animation: overlayFadeIn ease-in-out 200ms 1 forwards;
50
+ }
51
+
52
+ @keyframes overlayFadeIn {
53
+ 0% {
54
+ background-color: rgba(0, 0, 0, 0);
55
+ -webkit-backdrop-filter: blur(0);
56
+ backdrop-filter: blur(0);
57
+ }
58
+ 100% {
59
+ background-color: rgba(0, 0, 0, 0.5);
60
+ -webkit-backdrop-filter: blur(10px);
61
+ backdrop-filter: blur(10px);
62
+ }
63
+ }
64
+
65
+ /* html:has(.panel-container.popup.active) {
66
+ overflow: hidden !important;
67
+ } */
68
+
69
+
70
+ /* TODO - Review Code Below */
71
+
72
+ .panel-container.popup .panel.hidden .panel-background {
73
+ background-color: rgba(0, 0, 0, 0);
74
+ -webkit-backdrop-filter: blur(0);
75
+ backdrop-filter: blur(0);
76
+ position: fixed;
77
+ top: 0;
78
+ left: 0;
79
+ right: 0;
80
+ bottom: 0;
81
+ overflow: hidden;
82
+ z-index: 10000;
83
+ align-items: center;
84
+ justify-content: center;
85
+ animation: overlayFadeOut ease-in-out 200ms 1 forwards;
86
+ }
87
+
88
+ @keyframes overlayFadeOut {
89
+ 0% {
90
+ background-color: rgba(0, 0, 0, 0.5);
91
+ -webkit-backdrop-filter: blur(10px);
92
+ backdrop-filter: blur(10px);
93
+ }
94
+ 99% {
95
+ background-color: rgba(0, 0, 0, 0);
96
+ -webkit-backdrop-filter: blur(0);
97
+ backdrop-filter: blur(0);
98
+ }
99
+ 100% {
100
+ display: none;
101
+ position: relative;
102
+ }
103
+ }
104
+
105
+ .panel-container.popup .panel.hidden {
106
+ display: block !important;
107
+ }
108
+
109
+ .panel-container.popup .panel.hidden .panel-display {
110
+ animation: slideDown ease-in-out 200ms 1 forwards;
111
+ }
112
+
113
+ @keyframes slideDown {
114
+ 0% {
115
+ transform: translateY(0);
116
+ opacity: 1;
117
+ }
118
+ 100% {
119
+ transform: translateY(8%);
120
+ opacity: 0;
121
+ display: none;
122
+ }
123
+ }
@@ -0,0 +1,64 @@
1
+ module NitroRails
2
+ class SequenceController < ActionController::Base
3
+ layout 'application'
4
+
5
+ before_action :set_sequence
6
+
7
+ helper_method :next_step_in_sequence_path, :previous_step_in_sequence_path, :first_step_in_sequence_path, :last_step_in_sequence_path
8
+
9
+ def self.sequence(*steps)
10
+ @sequence = [:start, *steps, :finish]
11
+ end
12
+
13
+ def self.before_each_step(action)
14
+ before_action action, only: [:step, :finish]
15
+ end
16
+
17
+ def self.get_step_for(step)
18
+ return @sequence[step]
19
+ end
20
+
21
+ def redirect_to_step(step)
22
+ redirect_to self.class.get_step_for(step)
23
+ end
24
+
25
+ # Convenience Methods
26
+
27
+ def next_step_in_sequence_path(id = nil)
28
+ # binding.pry
29
+ url_for(request.params.slice(:controller).merge(action: @sequence[:next_step], id: id)) if @sequence[:next_step]
30
+ end
31
+
32
+ def previous_step_in_sequence_path
33
+ url_for(request.params.slice(:controller).merge(action: @sequence[:previous_step])) if @sequence[:previous_step]
34
+ end
35
+
36
+ def first_step_in_sequence_path(resource = nil)
37
+ url_for(request.params.slice(:controller).merge(action: @sequence[:first_step])) if @sequence[:first_step]
38
+ end
39
+
40
+ def last_step_in_sequence_path
41
+ url_for(request.params.slice(:controller).merge(action: @sequence[:last_step])) if @sequence[:last_step]
42
+ end
43
+
44
+ # Initialization Information
45
+ #
46
+ def start
47
+ redirect_to next_step_in_sequence_path
48
+ end
49
+
50
+ def set_sequence
51
+ steps = self.class.instance_variable_get(:@sequence)
52
+ current_step_index = steps.index(params[:action].gsub(/!/, "").to_sym)
53
+
54
+ @sequence = {
55
+ steps: steps,
56
+ first_step: steps[0],
57
+ previous_step: current_step_index <= 1 ? nil : steps[current_step_index - 1],
58
+ current_step: steps[current_step_index],
59
+ next_step: steps[current_step_index + 1],
60
+ last_step: steps[-1],
61
+ }
62
+ end
63
+ end
64
+ end
@@ -1,4 +1,45 @@
1
1
  module NitroRails
2
2
  module ApplicationHelper
3
+ def alert_message(message, threat=:notice)
4
+ content_tag(:div, message, class: "alert #{threat}")
5
+ end
6
+
7
+ def current_color_scheme
8
+ current_user && current_user.respond_to?(:settings) && current_user.settings.dark_mode? ? "dark-mode" : "light-mode"
9
+ end
10
+
11
+ def back_path(default = root_path)
12
+ params[:referrer] || default # Should we add in :back?
13
+ end
14
+
15
+ def polymorphize(record, polymorphic_type)
16
+ { "#{polymorphic_type}_id": record.id, "#{polymorphic_type}_type": record.class.name }
17
+ end
18
+
19
+ def contextual_day_format(date, offset: 0)
20
+ relative_date = Time.current.in_time_zone(offset).to_date
21
+ case (relative_date - date).to_i
22
+ when 0...1
23
+ "Today"
24
+ when 1...2
25
+ "Yesterday"
26
+ when 2...7
27
+ date.to_fs(:weekday)
28
+ else
29
+ if (relative_date.year == date.year)
30
+ date.to_fs(:month_and_day)
31
+ else
32
+ date.to_fs(:month_day_and_year)
33
+ end
34
+ end
35
+ end
36
+
37
+ def ios_app?
38
+ request.user_agent&.include?("iOS")
39
+ end
40
+
41
+ def android_app?
42
+ request.user_agent&.include?("Android")
43
+ end
3
44
  end
4
- end
45
+ end
@@ -0,0 +1,23 @@
1
+ module NitroRails
2
+ module ColorHelper
3
+ def brightness_indicator(color)
4
+ case brightness(color)
5
+ when 0..100
6
+ "dark"
7
+ when 101..200
8
+ "medium"
9
+ else
10
+ "light"
11
+ end
12
+ end
13
+
14
+ def brightness(color)
15
+ if color&.start_with?("#")
16
+ r = color[1..2].to_i(16)
17
+ g = color[3..4].to_i(16)
18
+ b = color[5..6].to_i(16)
19
+ (r * 299 + g * 587 + b * 114) / 1000
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,49 @@
1
+ module NitroRails
2
+ module ComponentsHelper
3
+ def inline_svg(path, **options)
4
+ nitro_options(options) do |options|
5
+ options.concat(:class, "inline-svg")
6
+ options.concat(:class, "svg-#{path.split("/").last}")
7
+ options.concat(:class, options.delete(:size))
8
+ options.concat(:style, "transform: rotate(#{options.delete(:rotate)}deg);") if options[:rotate]
9
+ end
10
+
11
+ # Rails.cache.clear
12
+ svg = Rails.cache.fetch("inline_svg/#{path}", expires_in: 12.hours) do
13
+ app_path = Rails.root.join("app/assets/images/svgs/#{path}.svg")
14
+ gem_path = NitroRails::Engine.root.join("app/assets/images/nitro_rails/#{path}.svg")
15
+
16
+ if File.exist?(app_path)
17
+ File.read(app_path).html_safe
18
+ elsif File.exist?(gem_path)
19
+ File.read(gem_path).html_safe
20
+ else
21
+ "(SVG file not found: #{path})"
22
+ end
23
+ end
24
+
25
+ content_tag(:div, **options) do
26
+ render inline: svg
27
+ end
28
+ end
29
+
30
+ def clock
31
+ content_tag(:div, class: "clock", data: { controller: "clock" }) do
32
+ content_tag(:span, Time.now.strftime("%-I:%M %p"), class: "clock-time", data: { "clock-target": "time" })
33
+ end
34
+ end
35
+
36
+ def search_bar(**options)
37
+ options[:class] = "search-bar #{options[:class]}"
38
+ options[:data] ||= {}
39
+ options[:data][:controller] = "search"
40
+
41
+ content_tag(:div, **options) do
42
+ content_tag(:i, "", class: "fas fa-search") +
43
+ form_with(url: '/', method: :get, data: { turbo: false }) do
44
+ text_field_tag(:query, params[:query], class: "search-bar-input", placeholder: "Search", data: { action: "keyup->search#search" })
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,48 @@
1
+ module NitroRails
2
+ module InlineEditHelper
3
+ def editable_text(resource_path, attribute, context: :broadcast, placeholder: nil, focus: false, tag: :p)
4
+ render partial: 'nitro_rails/editable_text', locals: {
5
+ resource_path: resource_path,
6
+ resource: resource_path.is_a?(Array) ? resource_path.last : resource_path,
7
+ attribute: attribute,
8
+ context: context,
9
+ placeholder: placeholder,
10
+ focus: focus,
11
+ tag: tag
12
+ }
13
+ end
14
+
15
+ def togglable_checkbox(resource_path, attribute, context: :broadcast)
16
+ render partial: 'nitro_rails/togglable_checkbox', locals: {
17
+ resource_path: resource_path,
18
+ resource: resource = resource_path.is_a?(Array) ? resource_path.last : resource_path,
19
+ attribute: attribute,
20
+ context: context
21
+ }
22
+ end
23
+
24
+ def updatable_text(resource, attribute, placeholder: nil)
25
+ content_tag(:span, resource.send(attribute).presence, class: "updatable-text", placeholder: placeholder, data: {
26
+ nitro_id: resource.nitro_id(attribute)
27
+ })
28
+ end
29
+
30
+ def error_badge(resource, attribute)
31
+ error_count = resource.errors[attribute].length
32
+ content_tag(:span, error_count, class: "error-badge #{'visible' if error_count > 0}", data: {
33
+ attribute_error_count_id: resource.nitro_id(attribute)
34
+ })
35
+ end
36
+
37
+ def error_message(resource, attribute)
38
+ error_message = resource.errors.full_messages_for(attribute).first
39
+ content_tag(:span, error_message, class: "error-message #{'visible' if error_message}", data: {
40
+ attribute_error_message_id: resource.nitro_id(attribute)
41
+ })
42
+ end
43
+
44
+ def attribute_classes(resource, attribute)
45
+ "#{resource.class.name.downcase.dasherize}-#{attribute} #{resource.class.name.downcase.dasherize}-#{resource.id}-#{attribute} #{attribute}"
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,178 @@
1
+ module NitroRails
2
+ module NitroActionHelper
3
+ def nitro_action_form(**options, &block)
4
+ nitro_hidden_action_form(**options) do |form|
5
+ form.submit_div(&block)
6
+ end
7
+ end
8
+
9
+ def nitro_action_button(text, **options, &block)
10
+ text ||= "Save" if !block_given?
11
+
12
+ nitro_hidden_action_form(**options) do |form|
13
+ form.submit(text, &block)
14
+ end
15
+ end
16
+
17
+ def nitro_hidden_action_form(**options, &block)
18
+ nitro_form(**options) do |form|
19
+ concat(form.generate_hidden_attribute_fields)
20
+ concat(yield(form))
21
+ end
22
+ end
23
+
24
+ ############
25
+ ## CREATE ##
26
+ ############
27
+
28
+ def nitro_create(type, **options, &block)
29
+ nitro_create_options(type, options)
30
+ nitro_action_form(**options, &block)
31
+ end
32
+
33
+ def nitro_create_button(text=nil, type, **options, &block)
34
+ nitro_create_options(type, options)
35
+ nitro_action_button(text, **options, &block)
36
+ end
37
+
38
+ def nitro_create_options(type, options)
39
+ nitro_options(options) do |options|
40
+ options.default(:method, :post)
41
+ options.default(:model, type.to_s.classify.constantize.new)
42
+ options.default(:params, type.to_sym => options.delete(:params) || {})
43
+ end
44
+ end
45
+
46
+ ##########
47
+ ## SAVE ##
48
+ ##########
49
+
50
+ def nitro_save(resource = current_nitro_resource, **options, &block)
51
+ nitro_save_options(resource, options)
52
+ nitro_action_form(**options, &block)
53
+ end
54
+
55
+ # No idea if any of the buttons are working
56
+ def nitro_save_button(text_or_resource = nil, maybe_resource = current_nitro_resource, **options, &block)
57
+ resource, text = button_args(text_or_resource, maybe_resource)
58
+ nitro_save_options(resource, options)
59
+ nitro_action_button(text, **options, &block)
60
+ end
61
+
62
+
63
+ def nitro_save_options(resource, options)
64
+ nitro_options(options) do |options|
65
+ options.default(:method, resource.persisted? ? :patch : :post)
66
+ options.default(:model, resource)
67
+ options.default(:params, resource.type.to_sym => options.delete(:params) || {})
68
+ end
69
+ end
70
+
71
+ ############
72
+ ## UPDATE ##
73
+ ############
74
+
75
+ def nitro_update(resource = current_nitro_resource, **options, &block)
76
+ nitro_update_options(resource, options)
77
+ nitro_action_form(**options, &block)
78
+ end
79
+
80
+ def nitro_update_button(text_or_resource = nil, maybe_resource = current_nitro_resource, **options, &block)
81
+ resource, text = button_args(text_or_resource, maybe_resource)
82
+ nitro_update_options(resource, options)
83
+ nitro_action_button(text, **options, &block)
84
+ end
85
+
86
+ def nitro_update_options(resource, options)
87
+ nitro_options(options) do |options|
88
+ options.default(:method, :patch)
89
+ options.default(:model, resource)
90
+ options.default(:params, resource.type.to_sym => options.delete(:params) || {})
91
+ end
92
+ end
93
+
94
+ #############
95
+ ## DESTROY ##
96
+ #############
97
+
98
+ def nitro_destroy(resource = current_nitro_resource, **options, &block)
99
+ nitro_destroy_options(resource, options)
100
+ nitro_action_form(**options, &block)
101
+ end
102
+
103
+ def nitro_destroy_button(text_or_resource = nil, maybe_resource = current_nitro_resource, **options, &block)
104
+ resource, text = button_args(text_or_resource, maybe_resource)
105
+ nitro_destroy_options(resource, options)
106
+ nitro_action_button(text, **options, &block)
107
+ end
108
+
109
+ def nitro_destroy_options(resource, options)
110
+ nitro_options(options) do |options|
111
+ options.default(:method, :delete)
112
+ options.default(:model, resource)
113
+ end
114
+ end
115
+
116
+ private
117
+
118
+ #############
119
+ ## HELPERS ##
120
+ #############
121
+
122
+ # Refactor at some point
123
+ def button_args(*args)
124
+ if args.length > 3
125
+ raise ArgumentError, "Too many arguments. Expected 0, 1, or 2 arguments."
126
+ end
127
+
128
+ if args.first == nil || args.first.is_a?(String) || args.first.is_a?(Symbol)
129
+ return [args.last, args.first]
130
+ end
131
+
132
+ if args.first.is_a?(ActiveRecord::Base)
133
+ return [args.first, nil]
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ ###########
140
+ ## STASH ##
141
+ ###########
142
+
143
+ # def nitro_create_button(text=nil, record_type, **opts, &block)
144
+ # options = { method: :post, data: { turbo: true, controller: "nitro", action: "nitro#insertNewItem" }}.merge(opts.delete(:options).to_h)
145
+ # params = { params: { record_type.to_sym => opts } }
146
+ # path = record_type.to_s.pluralize.to_sym
147
+
148
+ # forges = opts[:forges].is_a?(Array) ? opts[:forges] : [opts[:forges]].compact
149
+
150
+
151
+ # content_tag(:div, class: "nitro-form-stack") do
152
+ # forges.each do |forger|
153
+ # concat(forger_form(forger)) unless forger.persisted?
154
+ # end
155
+
156
+ # if block_given?
157
+ # concat(button_to(path, options.merge(params), &block))
158
+ # else
159
+ # concat(button_to(text || "Create #{record_type}", path, options.merge(params)))
160
+ # end
161
+ # end
162
+ # end
163
+ #
164
+ # def forger_form(forger)
165
+ # nitro_hidden_resource_form(forger) {}
166
+ # end
167
+ #
168
+ # def harvest_arguments(arguments, keys)
169
+ # output = []
170
+ # arguments.each_with_index do |argument, index|
171
+ # if keys[index] == :text? && (argument.is_a?(String) || argument.is_a?(Symbol)) || argument.nil?
172
+ # output << argument
173
+ # else
174
+ # output << arg
175
+
176
+ # end
177
+ # end
178
+ # end
@@ -0,0 +1,87 @@
1
+ module NitroRails
2
+ module NitroCollectionHelper
3
+ def nitro_collection_tag(tag = :ul, parent, resource_method, **options, &block)
4
+ nitro_options(options) do |options|
5
+ options.default(:nitro_id, parent.nitro_id(resource_method))
6
+ options.concat(:class, classify(resource_method))
7
+ options.concat(:class, classify(parent.type, resource_method))
8
+ end
9
+
10
+ nitro_tag(tag, **options, &block)
11
+ end
12
+
13
+ def nitro_collection(parent, resource_method, **options, &block)
14
+ content_tag(:div, data: { controller: "nitro-collection", nitro_collection_target: "container", nitro_collection_id: "#{parent.nitro_id}:#{resource_method}" }) do
15
+ nitro_collection_tag(:ul, parent, resource_method, data: { nitro_collection_target: :collection }, **options) do
16
+ resources = parent.send(resource_method)
17
+ resources = resources.order(options.delete(:order)) if options[:order]
18
+ resources = resources.where(options.delete(:where)) if options[:where]
19
+ resources = resources.take(options.delete(:take)) if options[:take]
20
+
21
+
22
+ resources.map do |resource|
23
+ yield resource
24
+ end
25
+ end +
26
+
27
+ content_tag(:template, class: "nitro-collection-template", style: "display: none;", data: { nitro_collection_target: :template }) do
28
+ yield parent.send(resource_method).template
29
+ end
30
+ end
31
+ end
32
+
33
+ def chain_methods(*array)
34
+ array.inject { |obj, method| obj.public_send(method) }
35
+ end
36
+
37
+ def new_nitro_collection(*resources_or_path, **options, &block)
38
+ resources = is_active_collection?(resources_or_path.first) ? resources_or_path.first : chain_methods(*resources_or_path)
39
+ NitroCollection.new(resources, view: self, **options).render_content(&block)
40
+ end
41
+
42
+ def is_active_collection?(collection)
43
+ collection.is_a?(ActiveRecord::Associations::CollectionProxy || ActiveRecord::Relation)
44
+ end
45
+ end
46
+ end
47
+
48
+
49
+ # resources: collection_proxy,
50
+ # resource_type: collection_proxy.proxy_association.reflection.klass.name.underscore,
51
+ # parent: collection_proxy.proxy_association.owner,
52
+ # where_clause: collection_proxy.where_clause,
53
+ # order_clause: collection_proxy.order_values,
54
+ # request_hash: collection_proxy.to_sql.hash
55
+
56
+
57
+ # class NitroCollection
58
+ # def initialize(**options)
59
+ # @parent = options[:affiliation]
60
+ # @method = options[:method]
61
+ # @order = options[:order]
62
+ # @resources = @parent.send(@method).order(options[:order])
63
+ # @type = options[:type] || @resources.first.class.name.underscore
64
+ # @method = method
65
+ # end
66
+
67
+ # def render_content(&block)
68
+
69
+ # end
70
+ # end
71
+
72
+ # def nitro_collection(tag = :ul, parent, resource_method, **options, &block)
73
+ # content_tag(:div, class: "nitro-collection-container") do
74
+ # nitro_collection_tag(tag, parent, resource_method, **options) do
75
+ # parent.send(resource_method).order(options[:order]).map do |resource|
76
+ # yield resource
77
+ # end
78
+ # end +
79
+
80
+ # content_tag(:template, class: "nitro-collection-template", style: "display: none;") do
81
+ # yield parent.send(resource_method).template
82
+ # end
83
+ # end
84
+ # end
85
+
86
+ # private?
87
+ # NitroCollection.new(affiliation: @day, method: :tasks, order: :created_at)
@@ -0,0 +1,15 @@
1
+ module NitroRails
2
+ module NitroEditHelper
3
+ def nitro_checkbox(record, attribute, **options)
4
+ nitro_options(options) do |options|
5
+ options.default(:method, :patch)
6
+ options.default(:data, :turbo, true)
7
+ options.concat(:data, :controller, "nitro-form")
8
+ options.concat(:data, :nitro_form_target, "form")
9
+ options.concat(:data, :nitro_form_resource_target_value, record.nitro_id)
10
+ end
11
+
12
+ render partial: 'nitro_rails/nitro_checkbox', locals: { record: record, attribute: attribute, options: options }
13
+ end
14
+ end
15
+ end