yummy-guide-generic-administrate 0.1.0

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 (43) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/README.md +243 -0
  4. data/Rakefile +11 -0
  5. data/app/assets/javascripts/yummy_guide_administrate/filter_form.js +219 -0
  6. data/app/assets/javascripts/yummy_guide_administrate/sticky_left_columns.js +141 -0
  7. data/app/assets/stylesheets/yummy_guide_administrate/components.scss +199 -0
  8. data/app/controllers/concerns/yummy_guide/administrate/datetime_filter_parameters.rb +40 -0
  9. data/app/controllers/concerns/yummy_guide/administrate/default_sorting.rb +46 -0
  10. data/app/dashboards/yummy_guide/administrate/application_dashboard.rb +46 -0
  11. data/app/fields/yummy_guide/administrate/fields/area/picture_field.rb +106 -0
  12. data/app/fields/yummy_guide/administrate/fields/json_pretty_field.rb +29 -0
  13. data/app/fields/yummy_guide/administrate/fields/version_item_field.rb +62 -0
  14. data/app/fields/yummy_guide/administrate/fields/version_whodunnit_field.rb +65 -0
  15. data/app/helpers/yummy_guide/administrate/collection_helper.rb +62 -0
  16. data/app/helpers/yummy_guide/administrate/filter_form_helper.rb +80 -0
  17. data/app/views/fields/yummy_guide_administrate/area/picture/_form.html.erb +36 -0
  18. data/app/views/fields/yummy_guide_administrate/area/picture/_index.html.erb +2 -0
  19. data/app/views/fields/yummy_guide_administrate/area/picture/_show.html.erb +24 -0
  20. data/app/views/fields/yummy_guide_administrate/json_pretty_field/_index.html.erb +2 -0
  21. data/app/views/fields/yummy_guide_administrate/json_pretty_field/_show.html.erb +6 -0
  22. data/app/views/fields/yummy_guide_administrate/version_item_field/_index.html.erb +2 -0
  23. data/app/views/fields/yummy_guide_administrate/version_item_field/_show.html.erb +6 -0
  24. data/app/views/fields/yummy_guide_administrate/version_whodunnit_field/_index.html.erb +2 -0
  25. data/app/views/fields/yummy_guide_administrate/version_whodunnit_field/_show.html.erb +6 -0
  26. data/app/views/yummy_guide/administrate/administrate/application/_collection.html.erb +62 -0
  27. data/app/views/yummy_guide/administrate/filter_forms/_checkbox_group.html.erb +30 -0
  28. data/app/views/yummy_guide/administrate/filter_forms/_datetime_field.html.erb +30 -0
  29. data/app/views/yummy_guide/administrate/filter_forms/_frame.html.erb +28 -0
  30. data/lib/generic/administrate.rb +3 -0
  31. data/lib/yummy_guide/administrate/engine.rb +18 -0
  32. data/lib/yummy_guide/administrate/version.rb +8 -0
  33. data/lib/yummy_guide/administrate.rb +13 -0
  34. data/spec/spec_helper.rb +25 -0
  35. data/spec/yummy_guide/administrate/application_dashboard_spec.rb +39 -0
  36. data/spec/yummy_guide/administrate/collection_helper_spec.rb +25 -0
  37. data/spec/yummy_guide/administrate/datetime_filter_parameters_spec.rb +52 -0
  38. data/spec/yummy_guide/administrate/fields/json_pretty_field_spec.rb +22 -0
  39. data/spec/yummy_guide/administrate/fields/version_item_field_spec.rb +30 -0
  40. data/spec/yummy_guide/administrate/fields/version_whodunnit_field_spec.rb +31 -0
  41. data/spec/yummy_guide/administrate/filter_form_helper_spec.rb +40 -0
  42. data/yummy-guide-generic-administrate.gemspec +38 -0
  43. metadata +156 -0
@@ -0,0 +1,199 @@
1
+ .scroll-table {
2
+ overflow-x: auto;
3
+ }
4
+
5
+ .scroll-table table th.sticky-left,
6
+ .scroll-table table td.sticky-left {
7
+ position: sticky;
8
+ background-clip: padding-box;
9
+ }
10
+
11
+ .scroll-table table th.sticky-left {
12
+ z-index: 4;
13
+ background-color: #121012;
14
+ }
15
+
16
+ .scroll-table table td.sticky-left {
17
+ z-index: 3;
18
+ background-color: var(--sticky-cell-background, #fff);
19
+ }
20
+
21
+ .scroll-table table th.sticky-left::after,
22
+ .scroll-table table td.sticky-left::after {
23
+ content: "";
24
+ position: absolute;
25
+ top: -1px;
26
+ right: -1px;
27
+ bottom: -1px;
28
+ width: 1px;
29
+ background-color: #fff;
30
+ pointer-events: none;
31
+ }
32
+
33
+ .scroll-table table th.sticky-left--last,
34
+ .scroll-table table td.sticky-left--last {
35
+ box-shadow: 6px 0 8px -8px rgba(0, 0, 0, 0.35);
36
+ }
37
+
38
+ .yummy-guide-administrate-filter-form {
39
+ display: flex;
40
+ flex-direction: column;
41
+ gap: 0;
42
+ background: #fff;
43
+ border: 1px solid #d7dce5;
44
+ border-radius: 12px;
45
+ box-shadow: 0 18px 44px rgba(15, 23, 42, 0.08);
46
+ overflow: hidden;
47
+ }
48
+
49
+ .yummy-guide-administrate-filter-form__title {
50
+ margin: 0;
51
+ padding: 20px 20px 16px;
52
+ font-size: 1.2rem;
53
+ }
54
+
55
+ .yummy-guide-administrate-filter-form__body {
56
+ padding: 0 20px;
57
+ }
58
+
59
+ .yummy-guide-administrate-filter-form .filter_table {
60
+ width: 100%;
61
+ }
62
+
63
+ .yummy-guide-administrate-filter-form .filter_table td {
64
+ padding: 8px 0;
65
+ vertical-align: top;
66
+ }
67
+
68
+ .yummy-guide-administrate-filter-form .filter_table td:first-child {
69
+ width: 160px;
70
+ font-weight: 600;
71
+ vertical-align: middle;
72
+ }
73
+
74
+ .yummy-guide-administrate-filter-form input[type="text"],
75
+ .yummy-guide-administrate-filter-form input[type="date"],
76
+ .yummy-guide-administrate-filter-form select,
77
+ .yummy-guide-administrate-filter-form textarea,
78
+ .yummy-guide-administrate-filter-form .filter-datetime-group__time {
79
+ width: 100%;
80
+ min-height: 40px;
81
+ height: 40px;
82
+ box-sizing: border-box;
83
+ border: 1px solid #dfe0e1;
84
+ border-radius: 5px;
85
+ background-color: #fff;
86
+ }
87
+
88
+ .yummy-guide-administrate-filter-form__actions {
89
+ display: flex;
90
+ gap: 8px;
91
+ justify-content: flex-end;
92
+ align-items: center;
93
+ flex-wrap: wrap;
94
+ padding: 12px 20px 20px;
95
+ background: #fff;
96
+ border-top: 1px solid #e5e7eb;
97
+ box-shadow: 0 -12px 24px rgba(15, 23, 42, 0.08);
98
+ }
99
+
100
+ .filter-datetime-group {
101
+ display: grid;
102
+ grid-template-columns: minmax(180px, 1fr) 88px auto 88px;
103
+ gap: 8px;
104
+ align-items: center;
105
+ }
106
+
107
+ .filter-datetime-group__separator,
108
+ .filter-datetime-range-separator {
109
+ text-align: center;
110
+ margin: 0;
111
+ min-height: 40px;
112
+ display: flex;
113
+ align-items: center;
114
+ justify-content: center;
115
+ }
116
+
117
+ .filter-checkbox-group {
118
+ display: grid;
119
+ gap: 12px;
120
+ }
121
+
122
+ .filter-checkbox-group__options {
123
+ display: grid;
124
+ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
125
+ gap: 8px 12px;
126
+ }
127
+
128
+ .filter-checkbox-group__actions {
129
+ display: flex;
130
+ gap: 8px;
131
+ justify-content: flex-end;
132
+ align-items: center;
133
+ flex-wrap: wrap;
134
+ }
135
+
136
+ .json-pretty-field {
137
+ margin: 0;
138
+ white-space: pre-wrap;
139
+ overflow-wrap: anywhere;
140
+ }
141
+
142
+ .yummy-guide-administrate-picture-list {
143
+ display: flex;
144
+ flex-wrap: wrap;
145
+ gap: 8px;
146
+ }
147
+
148
+ .yummy-guide-administrate-picture-list__item {
149
+ width: 200px;
150
+ }
151
+
152
+ .yummy-guide-administrate-picture-list__image {
153
+ display: block;
154
+ max-width: 100%;
155
+ border-radius: 8px;
156
+ }
157
+
158
+ .yummy-guide-administrate-picture-slots {
159
+ display: grid;
160
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
161
+ gap: 12px;
162
+ }
163
+
164
+ .yummy-guide-administrate-picture-slot {
165
+ display: grid;
166
+ gap: 8px;
167
+ align-content: start;
168
+ }
169
+
170
+ .yummy-guide-administrate-picture-slot__input {
171
+ width: 100%;
172
+ }
173
+
174
+ .yummy-guide-administrate-picture-slot__delete {
175
+ display: inline-flex;
176
+ gap: 6px;
177
+ align-items: center;
178
+ }
179
+
180
+ @media (max-width: 767px) {
181
+ .yummy-guide-administrate-filter-form__title {
182
+ padding: 16px 16px 12px;
183
+ }
184
+
185
+ .yummy-guide-administrate-filter-form__body {
186
+ padding: 0 16px;
187
+ }
188
+
189
+ .yummy-guide-administrate-filter-form__actions,
190
+ .filter-checkbox-group__actions {
191
+ flex-direction: column;
192
+ align-items: stretch;
193
+ }
194
+
195
+ .filter-datetime-group {
196
+ grid-template-columns: 1fr;
197
+ }
198
+ }
199
+
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YummyGuide
4
+ module Administrate
5
+ module DatetimeFilterParameters
6
+ extend ActiveSupport::Concern
7
+
8
+ private
9
+
10
+ def normalize_datetime_filter_params(filters, keys:)
11
+ return filters if filters.blank? || !filters.respond_to?(:deep_dup)
12
+
13
+ normalized_filters = filters.deep_dup
14
+
15
+ Array(keys).map(&:to_s).each do |key|
16
+ date_value = normalized_filters.delete("#{key}_date") || normalized_filters.delete("#{key}_date".to_sym)
17
+ hour_value = normalized_filters.delete("#{key}_hour") || normalized_filters.delete("#{key}_hour".to_sym)
18
+ minute_value = normalized_filters.delete("#{key}_minute") || normalized_filters.delete("#{key}_minute".to_sym)
19
+ next if date_value.nil? && hour_value.nil? && minute_value.nil?
20
+
21
+ date_value = date_value.to_s.strip
22
+ hour_value = hour_value.to_s.strip
23
+ minute_value = minute_value.to_s.strip
24
+
25
+ normalized_filters[key.to_sym] =
26
+ if date_value.blank?
27
+ nil
28
+ elsif hour_value.present? && minute_value.present?
29
+ "#{date_value}T#{hour_value}:#{minute_value}"
30
+ else
31
+ date_value
32
+ end
33
+ end
34
+
35
+ normalized_filters
36
+ end
37
+ end
38
+ end
39
+ end
40
+
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YummyGuide
4
+ module Administrate
5
+ module DefaultSorting
6
+ extend ActiveSupport::Concern
7
+
8
+ def default_sorting_attribute
9
+ dashboard_sorting_value(:default_sorting_attribute) || super
10
+ end
11
+
12
+ def default_sorting_direction
13
+ dashboard_sorting_value(:default_sorting_direction) || super
14
+ end
15
+
16
+ private
17
+
18
+ def sorting_requested?
19
+ order_present?(params) || sorting_param_keys.any? { |key| order_present?(params[key]) }
20
+ end
21
+
22
+ def dashboard_sorting_value(method_name)
23
+ current_dashboard = dashboard
24
+ return unless current_dashboard.respond_to?(method_name)
25
+
26
+ current_dashboard.public_send(method_name)
27
+ end
28
+
29
+ def sorting_param_keys
30
+ [
31
+ (resource_name if respond_to?(:resource_name, true)),
32
+ (resource_name.to_sym if respond_to?(:resource_name, true) && resource_name.present?),
33
+ controller_name.singularize,
34
+ controller_name.singularize.to_sym
35
+ ].compact.uniq
36
+ end
37
+
38
+ def order_present?(value)
39
+ return false unless value.is_a?(ActionController::Parameters) || value.is_a?(Hash)
40
+
41
+ value[:order].present? || value["order"].present?
42
+ end
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "administrate/base_dashboard"
4
+
5
+ module YummyGuide
6
+ module Administrate
7
+ class ApplicationDashboard < ::Administrate::BaseDashboard
8
+ INDEX_FIXED_COLUMNS_COUNT = 1
9
+
10
+ def default_sorting_attribute
11
+ :created_at
12
+ end
13
+
14
+ def default_sorting_direction
15
+ :desc
16
+ end
17
+
18
+ def self.index_fixed_columns_count
19
+ if const_defined?(:INDEX_FIXED_COLUMNS_COUNT, false)
20
+ const_get(:INDEX_FIXED_COLUMNS_COUNT)
21
+ elsif superclass.respond_to?(:index_fixed_columns_count)
22
+ superclass.index_fixed_columns_count
23
+ else
24
+ 0
25
+ end
26
+ end
27
+
28
+ def self.collection_sortable_attributes
29
+ if const_defined?(:COLLECTION_SORTABLE_ATTRIBUTES, false)
30
+ const_get(:COLLECTION_SORTABLE_ATTRIBUTES)
31
+ elsif const_defined?(:COLLECTION_ATTRIBUTES, false)
32
+ const_get(:COLLECTION_ATTRIBUTES)
33
+ elsif superclass.respond_to?(:collection_sortable_attributes)
34
+ superclass.collection_sortable_attributes
35
+ else
36
+ []
37
+ end
38
+ end
39
+
40
+ def self.collection_attribute_sortable?(attribute_name)
41
+ collection_sortable_attributes.map(&:to_sym).include?(attribute_name.to_sym)
42
+ end
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "administrate/field/base"
4
+
5
+ module YummyGuide
6
+ module Administrate
7
+ module Fields
8
+ module Area
9
+ class PictureField < ::Administrate::Field::Base
10
+ def self.field_type
11
+ "yummy_guide_administrate/area/picture"
12
+ end
13
+
14
+ def attachments
15
+ @attachments ||=
16
+ if data.respond_to?(:attachments)
17
+ data.attachments.to_a
18
+ elsif data.respond_to?(:attached?) && data.attached?
19
+ [data]
20
+ else
21
+ []
22
+ end
23
+ end
24
+
25
+ def max_uploads
26
+ resolved = resolve_option(:max_uploads)
27
+ resolved = resource.class::MAX_PICTURE_UPLOADS if resolved.blank? && resource.class.const_defined?(:MAX_PICTURE_UPLOADS)
28
+ resolved = attachments.size + 1 if resolved.blank?
29
+
30
+ [resolved.to_i, 1].max
31
+ end
32
+
33
+ def input_name
34
+ resolve_option(:input_name) || "#{resource_param_key}[#{attribute}][]"
35
+ end
36
+
37
+ def purge_input_name
38
+ resolve_option(:purge_input_name) || "#{resource_param_key}[#{attribute}_purge_ids][]"
39
+ end
40
+
41
+ def attachment_label(attachment)
42
+ return attachment.filename.to_s if attachment.respond_to?(:filename)
43
+
44
+ attachment.to_s
45
+ end
46
+
47
+ def attachment_identifier(attachment)
48
+ return attachment.id if attachment.respond_to?(:id) && attachment.id.present?
49
+ return attachment.blob_id if attachment.respond_to?(:blob_id) && attachment.blob_id.present?
50
+
51
+ nil
52
+ end
53
+
54
+ def attachment_url(attachment, view_context:)
55
+ resolve_attachment_url(:attachment_url, attachment, view_context: view_context) || preview_url(attachment, view_context: view_context)
56
+ end
57
+
58
+ def preview_url(attachment, view_context:)
59
+ resolve_attachment_url(:preview_url, attachment, view_context: view_context) || default_attachment_url(attachment, view_context: view_context)
60
+ end
61
+
62
+ private
63
+
64
+ def resource_param_key
65
+ resource.class.model_name.param_key
66
+ end
67
+
68
+ def resolve_option(name)
69
+ option = options[name]
70
+ if option.respond_to?(:call)
71
+ return option.call if option.arity.zero?
72
+ return option.call(resource) if option.arity == 1
73
+
74
+ return option.call(resource, attribute, data)
75
+ end
76
+
77
+ option
78
+ end
79
+
80
+ def resolve_attachment_url(name, attachment, view_context:)
81
+ resolver = options[name]
82
+ return unless resolver.respond_to?(:call)
83
+
84
+ case resolver.arity
85
+ when 0
86
+ resolver.call
87
+ when 1
88
+ resolver.call(attachment)
89
+ else
90
+ resolver.call(attachment, view_context)
91
+ end
92
+ end
93
+
94
+ def default_attachment_url(attachment, view_context:)
95
+ return attachment.url if attachment.respond_to?(:url)
96
+ return view_context.rails_blob_path(attachment, only_path: true) if attachment.respond_to?(:blob)
97
+
98
+ nil
99
+ rescue StandardError
100
+ nil
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "administrate/field/text"
4
+ require "json"
5
+
6
+ module YummyGuide
7
+ module Administrate
8
+ module Fields
9
+ class JsonPrettyField < ::Administrate::Field::Text
10
+ def self.field_type
11
+ "yummy_guide_administrate/json_pretty_field"
12
+ end
13
+
14
+ def to_s
15
+ return if data.blank?
16
+
17
+ if data.is_a?(String)
18
+ JSON.pretty_generate(JSON.parse(data))
19
+ else
20
+ JSON.pretty_generate(data.as_json)
21
+ end
22
+ rescue JSON::ParserError, TypeError
23
+ data.to_s
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YummyGuide
4
+ module Administrate
5
+ module Fields
6
+ class VersionItemField < ::Administrate::Field::Base
7
+ def self.field_type
8
+ "yummy_guide_administrate/version_item_field"
9
+ end
10
+
11
+ def target_resource
12
+ @target_resource ||= resolve_target_resource
13
+ end
14
+
15
+ def label
16
+ target = target_resource
17
+ return fallback_label if target.blank?
18
+
19
+ "#{target.class.name.demodulize} ##{target.id}"
20
+ end
21
+
22
+ def path
23
+ return if target_resource.blank?
24
+
25
+ Rails.application.routes.url_helpers.polymorphic_path([namespace, target_resource])
26
+ rescue StandardError
27
+ nil
28
+ end
29
+
30
+ def linkable?
31
+ path.present?
32
+ end
33
+
34
+ private
35
+
36
+ def namespace
37
+ options.fetch(:namespace, :admin)
38
+ end
39
+
40
+ def resolve_target_resource
41
+ item = data.presence || resource.reify
42
+ normalize_resource(item)
43
+ rescue StandardError
44
+ nil
45
+ end
46
+
47
+ def normalize_resource(item)
48
+ return if item.blank?
49
+
50
+ return item.globalized_model if item.respond_to?(:globalized_model) && item.globalized_model.present?
51
+
52
+ item
53
+ end
54
+
55
+ def fallback_label
56
+ "#{resource.item_type} ##{resource.item_id}"
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YummyGuide
4
+ module Administrate
5
+ module Fields
6
+ class VersionWhodunnitField < ::Administrate::Field::Base
7
+ def self.field_type
8
+ "yummy_guide_administrate/version_whodunnit_field"
9
+ end
10
+
11
+ def user
12
+ @user ||= user_class&.find_by(id: data)
13
+ end
14
+
15
+ def label
16
+ return if data.blank?
17
+
18
+ if user.present?
19
+ custom_label = options[:user_label]
20
+ return custom_label.call(user) if custom_label.respond_to?(:call)
21
+
22
+ if defined?(::UserDashboard)
23
+ dashboard = ::UserDashboard.new
24
+ return dashboard.display_resource(user) if dashboard.respond_to?(:display_resource)
25
+ end
26
+
27
+ return user.full_name if user.respond_to?(:full_name) && user.full_name.present?
28
+ return user.name if user.respond_to?(:name) && user.name.present?
29
+
30
+ "#{user.class.model_name.human} ##{user.id}"
31
+ else
32
+ "User ##{data}"
33
+ end
34
+ end
35
+
36
+ def path
37
+ return if user.blank?
38
+
39
+ Rails.application.routes.url_helpers.polymorphic_path([namespace, user])
40
+ rescue StandardError
41
+ nil
42
+ end
43
+
44
+ def linkable?
45
+ path.present?
46
+ end
47
+
48
+ private
49
+
50
+ def namespace
51
+ options.fetch(:namespace, :admin)
52
+ end
53
+
54
+ def user_class
55
+ candidate = options[:user_class]
56
+ return candidate if candidate.is_a?(Class)
57
+ return candidate.safe_constantize if candidate.respond_to?(:safe_constantize)
58
+
59
+ ::User if defined?(::User)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YummyGuide
4
+ module Administrate
5
+ module CollectionHelper
6
+ def yummy_guide_administrate_collection_table_fixed_columns_count(page:, collection_presenter:)
7
+ return 0 unless page.respond_to?(:instance_variable_defined?) && page.instance_variable_defined?(:@dashboard)
8
+
9
+ dashboard = page.instance_variable_get(:@dashboard)
10
+ return 0 unless dashboard&.class&.respond_to?(:index_fixed_columns_count)
11
+
12
+ fixed_columns_count = dashboard.class.index_fixed_columns_count.to_i
13
+ fixed_columns_count = 0 if fixed_columns_count.negative?
14
+
15
+ attribute_count = collection_presenter.attribute_types.size
16
+ [fixed_columns_count, attribute_count].min
17
+ rescue NoMethodError
18
+ 0
19
+ end
20
+
21
+ def yummy_guide_administrate_collection_detail_path(resource, namespace:)
22
+ return if resource.blank?
23
+ return if respond_to?(:accessible_action?) && !accessible_action?(resource, :show)
24
+
25
+ polymorphic_path([namespace, resource])
26
+ rescue StandardError
27
+ nil
28
+ end
29
+
30
+ def yummy_guide_administrate_collection_attribute_path(attribute:, resource:, namespace:)
31
+ if yummy_guide_administrate_collection_reference_link?(attribute)
32
+ yummy_guide_administrate_collection_detail_path(attribute.data, namespace: namespace)
33
+ elsif yummy_guide_administrate_collection_text_link?(attribute)
34
+ yummy_guide_administrate_collection_detail_path(resource, namespace: namespace)
35
+ end
36
+ end
37
+
38
+ def yummy_guide_administrate_collection_reference_link?(attribute)
39
+ attribute.is_a?(::Administrate::Field::BelongsTo) && attribute.data.present?
40
+ end
41
+
42
+ def yummy_guide_administrate_collection_text_link?(attribute)
43
+ attribute.respond_to?(:name) && attribute.name.to_s == "id"
44
+ end
45
+
46
+ def yummy_guide_administrate_collection_wrap(content, href:)
47
+ return content if href.blank?
48
+
49
+ link_to(href, class: "action-show") { content }
50
+ end
51
+
52
+ def yummy_guide_administrate_collection_actions_partial(partial_name)
53
+ if controller.respond_to?(:controller_path)
54
+ controller_partial = "#{controller.controller_path}/#{partial_name}"
55
+ return controller_partial if lookup_context.exists?(controller_partial, [], true)
56
+ end
57
+
58
+ "administrate/application/#{partial_name}"
59
+ end
60
+ end
61
+ end
62
+ end