flexi_admin 0.0.5
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 +7 -0
- data/README.md +42 -0
- data/Rakefile +7 -0
- data/lib/flexi_admin/components/actions/checkbox_component.html.slim +8 -0
- data/lib/flexi_admin/components/actions/checkbox_component.rb +13 -0
- data/lib/flexi_admin/components/actions/select_component.html.slim +11 -0
- data/lib/flexi_admin/components/actions/select_component.rb +17 -0
- data/lib/flexi_admin/components/base_component.rb +19 -0
- data/lib/flexi_admin/components/form/field_component.rb +11 -0
- data/lib/flexi_admin/components/form/label_component.html.slim +2 -0
- data/lib/flexi_admin/components/form/label_component.rb +13 -0
- data/lib/flexi_admin/components/form/rows_component.rb +9 -0
- data/lib/flexi_admin/components/form/text_input_component.html.slim +5 -0
- data/lib/flexi_admin/components/form/text_input_component.rb +17 -0
- data/lib/flexi_admin/components/helpers/action_button_helper.rb +28 -0
- data/lib/flexi_admin/components/helpers/action_helper.rb +12 -0
- data/lib/flexi_admin/components/helpers/icon_helper.rb +11 -0
- data/lib/flexi_admin/components/helpers/link_helper.rb +8 -0
- data/lib/flexi_admin/components/helpers/resource_helper.rb +71 -0
- data/lib/flexi_admin/components/helpers/selectable.rb +11 -0
- data/lib/flexi_admin/components/helpers/url_helper.rb +8 -0
- data/lib/flexi_admin/components/helpers/value_formatter.rb +32 -0
- data/lib/flexi_admin/components/nav/floating_toc_component.html.slim +2 -0
- data/lib/flexi_admin/components/nav/floating_toc_component.rb +6 -0
- data/lib/flexi_admin/components/resource/autocomplete_component.html.slim +30 -0
- data/lib/flexi_admin/components/resource/autocomplete_component.rb +83 -0
- data/lib/flexi_admin/components/resource/button_select_component.html.slim +13 -0
- data/lib/flexi_admin/components/resource/button_select_component.rb +19 -0
- data/lib/flexi_admin/components/resource/form_component.rb +18 -0
- data/lib/flexi_admin/components/resource/form_element_component.html.slim +3 -0
- data/lib/flexi_admin/components/resource/form_element_component.rb +31 -0
- data/lib/flexi_admin/components/resource/form_mixin.rb +287 -0
- data/lib/flexi_admin/components/resource/link_action_component.html.slim +8 -0
- data/lib/flexi_admin/components/resource/link_action_component.rb +16 -0
- data/lib/flexi_admin/components/resource/show_page_component.rb +21 -0
- data/lib/flexi_admin/components/resource/view_component.html.slim +26 -0
- data/lib/flexi_admin/components/resource/view_component.rb +22 -0
- data/lib/flexi_admin/components/resources/bulk_action/button_component.html.slim +7 -0
- data/lib/flexi_admin/components/resources/bulk_action/button_component.rb +29 -0
- data/lib/flexi_admin/components/resources/bulk_action/modal_component.html.slim +32 -0
- data/lib/flexi_admin/components/resources/bulk_action/modal_component.rb +54 -0
- data/lib/flexi_admin/components/resources/grid_view/card_component.html.slim +18 -0
- data/lib/flexi_admin/components/resources/grid_view/card_component.rb +65 -0
- data/lib/flexi_admin/components/resources/grid_view/grid_component.html.slim +10 -0
- data/lib/flexi_admin/components/resources/grid_view/grid_component.rb +16 -0
- data/lib/flexi_admin/components/resources/grid_view_component.rb +89 -0
- data/lib/flexi_admin/components/resources/index_page_component.html.slim +13 -0
- data/lib/flexi_admin/components/resources/index_page_component.rb +19 -0
- data/lib/flexi_admin/components/resources/list_view/cell_component.html.slim +2 -0
- data/lib/flexi_admin/components/resources/list_view/cell_component.rb +26 -0
- data/lib/flexi_admin/components/resources/list_view/table_component.html.slim +17 -0
- data/lib/flexi_admin/components/resources/list_view/table_component.rb +21 -0
- data/lib/flexi_admin/components/resources/list_view_component.rb +80 -0
- data/lib/flexi_admin/components/resources/pagination_component.html.slim +42 -0
- data/lib/flexi_admin/components/resources/pagination_component.rb +64 -0
- data/lib/flexi_admin/components/resources/resources_component.rb +34 -0
- data/lib/flexi_admin/components/resources/switch_view_component.html.slim +16 -0
- data/lib/flexi_admin/components/resources/switch_view_component.rb +45 -0
- data/lib/flexi_admin/components/resources/view_component.html.slim +12 -0
- data/lib/flexi_admin/components/resources/view_component.rb +15 -0
- data/lib/flexi_admin/components/shared/alert_component.html.slim +2 -0
- data/lib/flexi_admin/components/shared/alert_component.rb +11 -0
- data/lib/flexi_admin/components/shared/autocomplete/results_component.html.slim +15 -0
- data/lib/flexi_admin/components/shared/autocomplete/results_component.rb +50 -0
- data/lib/flexi_admin/components/shared/autocomplete.rb +6 -0
- data/lib/flexi_admin/components/shared/datalist_component.html.slim +24 -0
- data/lib/flexi_admin/components/shared/datalist_component.rb +20 -0
- data/lib/flexi_admin/components/shared/link_component.html.slim +3 -0
- data/lib/flexi_admin/components/shared/link_component.rb +15 -0
- data/lib/flexi_admin/components/shared/medium_component.html.slim +7 -0
- data/lib/flexi_admin/components/shared/medium_component.rb +51 -0
- data/lib/flexi_admin/components/shared/table/header_item_component.html.slim +9 -0
- data/lib/flexi_admin/components/shared/table/header_item_component.rb +78 -0
- data/lib/flexi_admin/components/shared/trix_component.html.slim +22 -0
- data/lib/flexi_admin/components/shared/trix_component.rb +21 -0
- data/lib/flexi_admin/components.rb +87 -0
- data/lib/flexi_admin/config.rb +24 -0
- data/lib/flexi_admin/controllers/modals_controller.rb +13 -0
- data/lib/flexi_admin/controllers/resources_controller.rb +240 -0
- data/lib/flexi_admin/controllers.rb +9 -0
- data/lib/flexi_admin/engine.rb +34 -0
- data/lib/flexi_admin/helpers/application_helper.rb +4 -0
- data/lib/flexi_admin/helpers.rb +8 -0
- data/lib/flexi_admin/javascript/controllers/application.js +9 -0
- data/lib/flexi_admin/javascript/controllers/autocomplete_controller.js +142 -0
- data/lib/flexi_admin/javascript/controllers/bulk_action_controller.js +158 -0
- data/lib/flexi_admin/javascript/controllers/button_select_controller.js +32 -0
- data/lib/flexi_admin/javascript/controllers/datalist_controller.js +104 -0
- data/lib/flexi_admin/javascript/controllers/floating_toc_controller.js +39 -0
- data/lib/flexi_admin/javascript/controllers/form_controller.js +17 -0
- data/lib/flexi_admin/javascript/controllers/form_validation_controller.js +86 -0
- data/lib/flexi_admin/javascript/controllers/index.js +44 -0
- data/lib/flexi_admin/javascript/controllers/pagination_controller.js +13 -0
- data/lib/flexi_admin/javascript/controllers/sorting_controller.js +17 -0
- data/lib/flexi_admin/javascript/controllers/switch_view_controller.js +15 -0
- data/lib/flexi_admin/javascript/controllers/toast_controller.js +18 -0
- data/lib/flexi_admin/javascript/controllers/trix_controller.js +32 -0
- data/lib/flexi_admin/javascript/controllers/uploads_controller.js +164 -0
- data/lib/flexi_admin/javascript/flexi_admin.js +4 -0
- data/lib/flexi_admin/javascript/utils.js +26 -0
- data/lib/flexi_admin/models/concerns/application_resource.rb +25 -0
- data/lib/flexi_admin/models/concerns/parentable.rb +17 -0
- data/lib/flexi_admin/models/context_params.rb +127 -0
- data/lib/flexi_admin/models/resources/context.rb +59 -0
- data/lib/flexi_admin/models/struct.rb +29 -0
- data/lib/flexi_admin/models/toast.rb +23 -0
- data/lib/flexi_admin/models.rb +20 -0
- data/lib/flexi_admin/prompts/codegen-system-prompt.md +50 -0
- data/lib/flexi_admin/railtie.rb +78 -0
- data/lib/flexi_admin/routes.rb +15 -0
- data/lib/flexi_admin/services/code_gen/code_export.rb +22 -0
- data/lib/flexi_admin/services/code_gen/gemini.rb +104 -0
- data/lib/flexi_admin/services/code_gen/gpt.rb +68 -0
- data/lib/flexi_admin/services/code_gen/runner.rb +210 -0
- data/lib/flexi_admin/services/code_gen.rb +14 -0
- data/lib/flexi_admin/services/create_resource.rb +32 -0
- data/lib/flexi_admin/services/update_resource.rb +30 -0
- data/lib/flexi_admin/services.rb +10 -0
- data/lib/flexi_admin/version.rb +10 -0
- data/lib/flexi_admin/views/shared/_redirect.slim +2 -0
- data/lib/flexi_admin/views/shared/_reload.slim +2 -0
- data/lib/flexi_admin/views/shared/_toasts.slim +15 -0
- data/lib/flexi_admin/views/shared/not_authorized.slim +11 -0
- data/lib/flexi_admin.rb +58 -0
- data/lib/tasks/flexi_admin.rake +49 -0
- data/lib/tasks/semantic.rake +57 -0
- metadata +333 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlexiAdmin::Components::Shared
|
4
|
+
class MediumComponent < FlexiAdmin::Components::BaseComponent
|
5
|
+
attr_accessor :attachment, :variant, :autoplay, :css_class
|
6
|
+
|
7
|
+
renders_one :preview_missing
|
8
|
+
|
9
|
+
# attachment: ActiveStorage::Attached::One
|
10
|
+
def initialize(attachment:, variant:, autoplay: false, css_class: nil)
|
11
|
+
@attachment = attachment
|
12
|
+
@variant = variant
|
13
|
+
@autoplay = autoplay
|
14
|
+
@css_class = css_class
|
15
|
+
end
|
16
|
+
|
17
|
+
def media?
|
18
|
+
return false if attachment.blank?
|
19
|
+
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def image_src
|
24
|
+
return if attachment.blank?
|
25
|
+
return unless attachment.attached?
|
26
|
+
|
27
|
+
if attachment.class != ActiveStorage::Attached::One
|
28
|
+
raise "ActiveStorage::Attached::One required, got #{attachment.class}"
|
29
|
+
end
|
30
|
+
|
31
|
+
return helpers.url_for(attachment) unless variant
|
32
|
+
|
33
|
+
helpers.url_for(attachment.variant(variant))
|
34
|
+
rescue ActiveStorage::InvariableError
|
35
|
+
helpers.url_for(attachment)
|
36
|
+
end
|
37
|
+
|
38
|
+
def render_media
|
39
|
+
case attachment.content_type.split("/").first
|
40
|
+
when "image"
|
41
|
+
content_tag :img, nil, src: image_src, class: css_class
|
42
|
+
when "video"
|
43
|
+
content_tag :video, nil, src: image_src,
|
44
|
+
controls: true,
|
45
|
+
class: css_class,
|
46
|
+
onmouseover: autoplay ? "this.play()" : nil,
|
47
|
+
onmouseout: autoplay ? "this.pause()" : nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
|
2
|
+
div class="#{merged_classes}" data-controller="sorting" data-sorting-sort-path-value="#{sort_path}"
|
3
|
+
- if column.sortable?
|
4
|
+
a href="#" class="a text-decoration-none text-secondary" data-action="sorting#sort"
|
5
|
+
.d-flex class="#{justify_class}"
|
6
|
+
= label
|
7
|
+
i.bi.text-primary.opacity-75.ms-2 class="#{sort_icon}"
|
8
|
+
- else
|
9
|
+
= label
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlexiAdmin::Components::Shared::Table
|
4
|
+
class HeaderItemComponent < FlexiAdmin::Components::BaseComponent
|
5
|
+
attr_reader :column, :attr, :justify, :width, :sort_by
|
6
|
+
|
7
|
+
def initialize(column)
|
8
|
+
@column = column
|
9
|
+
@justify = column.options[:justify] || :start
|
10
|
+
@width = column.options[:width] || ""
|
11
|
+
@attr = column.attribute
|
12
|
+
@sort_by = column.sort_by
|
13
|
+
@label = column.label
|
14
|
+
end
|
15
|
+
|
16
|
+
def label
|
17
|
+
@label || attr.to_s.humanize
|
18
|
+
end
|
19
|
+
|
20
|
+
def sort_path
|
21
|
+
if order.blank?
|
22
|
+
view_context.context.params.to_path(request.path)
|
23
|
+
else
|
24
|
+
view_context.context.params.merge({ sort: sort_by, order: }).to_path(request.path)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def merged_classes
|
29
|
+
[width_class, justify_class].join(" ")
|
30
|
+
end
|
31
|
+
|
32
|
+
def width_class
|
33
|
+
width.present? ? "col-#{width}" : "col"
|
34
|
+
end
|
35
|
+
|
36
|
+
def justify_class
|
37
|
+
case justify.to_sym
|
38
|
+
when :start
|
39
|
+
"justify-content-start"
|
40
|
+
when :end
|
41
|
+
"justify-content-end"
|
42
|
+
else
|
43
|
+
"justify-content-start"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def sort_icon
|
48
|
+
return "bi-arrow-up-square" if view_context.context.params[:sort].to_s != sort_by.to_s
|
49
|
+
|
50
|
+
case view_context.context.params[:order]
|
51
|
+
when "asc"
|
52
|
+
"bi-arrow-up-square-fill"
|
53
|
+
when "desc"
|
54
|
+
"bi-arrow-down-square-fill"
|
55
|
+
else
|
56
|
+
"bi-arrow-up-square"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def order
|
61
|
+
# Sorting by other column, so we need to reset the order
|
62
|
+
return "asc" if view_context.context.params[:sort].to_s != sort_by.to_s
|
63
|
+
|
64
|
+
order = case view_context.context.params[:order]
|
65
|
+
when "asc"
|
66
|
+
"desc"
|
67
|
+
when "desc"
|
68
|
+
"default"
|
69
|
+
when "default"
|
70
|
+
"asc"
|
71
|
+
else
|
72
|
+
"asc"
|
73
|
+
end
|
74
|
+
|
75
|
+
order
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
.trix-container.collapsed [data-controller="trix"
|
2
|
+
data-trix-disabled-value="#{disabled}"
|
3
|
+
data-trix-collapsed-value="true"]
|
4
|
+
- if disabled && value.present?
|
5
|
+
.collapsed data-trix-target="container"
|
6
|
+
- if short_text?
|
7
|
+
= value&.html_safe
|
8
|
+
- else
|
9
|
+
span.trigger [type="button"
|
10
|
+
data-trix-target="trigger"
|
11
|
+
data-action="click->trix#toggleCollapse"]
|
12
|
+
| rozbalit
|
13
|
+
span.text data-trix-target="text"
|
14
|
+
= value&.html_safe
|
15
|
+
|
16
|
+
- if !disabled
|
17
|
+
input [type="hidden"
|
18
|
+
name="#{attr_name}"
|
19
|
+
value="#{value}"
|
20
|
+
id="#{element_id}"]
|
21
|
+
trix-editor [input="#{element_id}"
|
22
|
+
data-trix-target="editor"]
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlexiAdmin::Components::Shared
|
4
|
+
class TrixComponent < FlexiAdmin::Components::BaseComponent
|
5
|
+
attr_reader :attr_name, :value, :disabled
|
6
|
+
|
7
|
+
def initialize(attr_name:, value:, disabled: false)
|
8
|
+
@attr_name = attr_name
|
9
|
+
@value = value
|
10
|
+
@disabled = disabled
|
11
|
+
end
|
12
|
+
|
13
|
+
def element_id
|
14
|
+
"trix-input-#{@attr_name}" || SecureRandom.uuid
|
15
|
+
end
|
16
|
+
|
17
|
+
def short_text?
|
18
|
+
value.present? && value.size < 150
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlexiAdmin
|
4
|
+
module Components
|
5
|
+
module Actions; end
|
6
|
+
module Form; end
|
7
|
+
module Helpers; end
|
8
|
+
module Resource; end
|
9
|
+
|
10
|
+
module Resources
|
11
|
+
module ListView; end
|
12
|
+
module GridView; end
|
13
|
+
module BulkAction; end
|
14
|
+
end
|
15
|
+
|
16
|
+
module Shared
|
17
|
+
module Table; end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Base Component
|
23
|
+
require_relative "components/base_component"
|
24
|
+
|
25
|
+
# Nav Components
|
26
|
+
require_relative "components/nav/floating_toc_component"
|
27
|
+
|
28
|
+
# Helpers
|
29
|
+
require_relative "components/helpers/action_button_helper"
|
30
|
+
require_relative "components/helpers/action_helper"
|
31
|
+
require_relative "components/helpers/icon_helper"
|
32
|
+
require_relative "components/helpers/link_helper"
|
33
|
+
require_relative "components/helpers/url_helper"
|
34
|
+
require_relative "components/helpers/resource_helper"
|
35
|
+
require_relative "components/helpers/selectable"
|
36
|
+
require_relative "components/helpers/value_formatter"
|
37
|
+
|
38
|
+
require_relative "components/resource/form_mixin"
|
39
|
+
|
40
|
+
# Action Components
|
41
|
+
require_relative "components/actions/checkbox_component"
|
42
|
+
require_relative "components/actions/select_component"
|
43
|
+
|
44
|
+
# Form Components
|
45
|
+
require_relative "components/form/field_component"
|
46
|
+
require_relative "components/form/label_component"
|
47
|
+
require_relative "components/form/rows_component"
|
48
|
+
require_relative "components/form/text_input_component"
|
49
|
+
|
50
|
+
# Resource Components
|
51
|
+
require_relative "components/resource/autocomplete_component"
|
52
|
+
require_relative "components/resource/button_select_component"
|
53
|
+
require_relative "components/resource/form_component"
|
54
|
+
require_relative "components/resource/form_element_component"
|
55
|
+
require_relative "components/resource/link_action_component"
|
56
|
+
require_relative "components/resource/show_page_component"
|
57
|
+
require_relative "components/resource/view_component"
|
58
|
+
|
59
|
+
# Resources Component
|
60
|
+
require_relative "components/resources/index_page_component"
|
61
|
+
require_relative "components/resources/list_view_component"
|
62
|
+
require_relative "components/resources/pagination_component"
|
63
|
+
require_relative "components/resources/resources_component"
|
64
|
+
require_relative "components/resources/switch_view_component"
|
65
|
+
require_relative "components/resources/view_component"
|
66
|
+
|
67
|
+
# Shared Components
|
68
|
+
require_relative "components/shared/autocomplete/results_component"
|
69
|
+
require_relative "components/shared/datalist_component"
|
70
|
+
require_relative "components/shared/medium_component"
|
71
|
+
require_relative "components/shared/table/header_item_component"
|
72
|
+
require_relative "components/shared/trix_component"
|
73
|
+
require_relative "components/shared/link_component"
|
74
|
+
|
75
|
+
# Resources List View Components
|
76
|
+
require_relative "components/resources/list_view/cell_component"
|
77
|
+
require_relative "components/resources/list_view/table_component"
|
78
|
+
|
79
|
+
# Resources Grid View Components
|
80
|
+
require_relative "components/resources/grid_view/card_component"
|
81
|
+
require_relative "components/resources/grid_view/grid_component"
|
82
|
+
require_relative "components/resources/grid_view_component"
|
83
|
+
require_relative "components/resources/list_view_component"
|
84
|
+
|
85
|
+
# Bulk Action Components
|
86
|
+
require_relative "components/resources/bulk_action/modal_component"
|
87
|
+
require_relative "components/resources/bulk_action/button_component"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlexiAdmin
|
4
|
+
class Config
|
5
|
+
class Store
|
6
|
+
attr_accessor :chat_client, :llm_client
|
7
|
+
attr_reader :functions
|
8
|
+
|
9
|
+
attr_writer :controller_class
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_writer :configuration
|
14
|
+
|
15
|
+
def configuration
|
16
|
+
@configuration ||= FlexiAdmin::Config::Store.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def configure
|
20
|
+
yield(configuration)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlexiAdmin::Controllers::ModalsController
|
4
|
+
def show
|
5
|
+
component_class = params[:kind].gsub("-", "/").camelize.constantize
|
6
|
+
|
7
|
+
raise ArgumentError, "scope is required" if context_params.scope.blank?
|
8
|
+
|
9
|
+
context = FlexiAdmin::Models::Resources::Context.from_params(context_params)
|
10
|
+
|
11
|
+
render turbo_stream: turbo_stream.update("modalx_#{context.scope}", component_class.new(context))
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlexiAdmin::Controllers::ResourcesController
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
# rescue_from RuntimeError, with: :handle_runtime_error
|
6
|
+
|
7
|
+
included do
|
8
|
+
before_action :context_params
|
9
|
+
|
10
|
+
rescue_from CanCan::AccessDenied do |exception|
|
11
|
+
flash[:error] = FlexiAdmin::Models::Toast.new(exception.message)
|
12
|
+
respond_to do |format|
|
13
|
+
format.html do
|
14
|
+
render 'shared/not_authorized'
|
15
|
+
end
|
16
|
+
format.turbo_stream do
|
17
|
+
render_toasts
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def render_toasts
|
24
|
+
render turbo_stream: turbo_stream.append('toasts', partial: 'shared/toasts')
|
25
|
+
end
|
26
|
+
|
27
|
+
def append_toasts
|
28
|
+
turbo_stream.append('toasts', partial: 'shared/toasts')
|
29
|
+
end
|
30
|
+
|
31
|
+
def render_index(resources, target: nil)
|
32
|
+
target ||= context_params.frame
|
33
|
+
respond_to do |format|
|
34
|
+
format.html do
|
35
|
+
component_class = "Admin::#{resource_class.name}::IndexPageComponent".constantize
|
36
|
+
puts "component_class: #{component_class}"
|
37
|
+
render component_class.new(resources, context_params:, scope: resource_class.to_s.downcase)
|
38
|
+
end
|
39
|
+
format.turbo_stream do
|
40
|
+
component_class = "Admin::#{resource_class.name}::ResourcesComponent".constantize
|
41
|
+
render turbo_stream: turbo_stream.replace(target, component_class.new(resources, context_params:, scope: resource_class.to_s.downcase))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Deprecated
|
47
|
+
def reload_page
|
48
|
+
render turbo_stream: [
|
49
|
+
turbo_stream.append('system', partial: 'shared/reload'),
|
50
|
+
turbo_stream.append('toasts', partial: 'shared/toasts')
|
51
|
+
]
|
52
|
+
end
|
53
|
+
|
54
|
+
def redirect_to_path(path)
|
55
|
+
render turbo_stream: turbo_stream.append('system', partial: 'shared/redirect', locals: { path: })
|
56
|
+
end
|
57
|
+
|
58
|
+
def context_params
|
59
|
+
@context_params ||= FlexiAdmin::Models::ContextParams.new(context_permitted_params)
|
60
|
+
end
|
61
|
+
|
62
|
+
def context_permitted_params
|
63
|
+
@context_permitted_params ||= params.permit(*FlexiAdmin::Models::ContextParams.permitted_params_keys)
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def handle_runtime_error(error)
|
68
|
+
return BugTracker.notify(error) if true
|
69
|
+
|
70
|
+
flash[:error] = FlexiAdmin::Models::Toast.new(error.message)
|
71
|
+
|
72
|
+
render_toasts
|
73
|
+
end
|
74
|
+
|
75
|
+
def create
|
76
|
+
authorize! :create, resource_class
|
77
|
+
|
78
|
+
create_service = begin
|
79
|
+
"#{resource_class.model_name.plural.camelize}::Services::Create".constantize
|
80
|
+
rescue NameError
|
81
|
+
FlexiAdmin::Services::CreateResource
|
82
|
+
end
|
83
|
+
|
84
|
+
result = create_service.run(resource_class:, params: create_params)
|
85
|
+
|
86
|
+
if result.valid?
|
87
|
+
redirect_to_path polymorphic_path([:admin, result.resource])
|
88
|
+
else
|
89
|
+
render_new_resource_form(result.resource)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def show
|
94
|
+
@resource = resource_class.find(params[:id])
|
95
|
+
authorize! :show, @resource
|
96
|
+
|
97
|
+
respond_to do |format|
|
98
|
+
format.html do
|
99
|
+
component ||= "Admin::#{resource_class.name}::Show::PageComponent".constantize
|
100
|
+
render component.new(@resource, context_params:, scope: resource_class.to_s.downcase)
|
101
|
+
end
|
102
|
+
format.turbo_stream do
|
103
|
+
render turbo_stream: turbo_stream.replace(context_params.frame)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def edit
|
109
|
+
@resource = resource_class.find(params[:id])
|
110
|
+
authorize! :update, @resource
|
111
|
+
|
112
|
+
render_edit_resource_form(disabled: disabled?(context_params.form_disabled))
|
113
|
+
end
|
114
|
+
|
115
|
+
def update
|
116
|
+
@resource = resource_class.find(params[:id])
|
117
|
+
authorize! :update, @resource
|
118
|
+
|
119
|
+
update_service = begin
|
120
|
+
"#{resource_class.model_name.plural.camelize}::Services::Update".constantize
|
121
|
+
rescue NameError
|
122
|
+
FlexiAdmin::Services::UpdateResource
|
123
|
+
end
|
124
|
+
|
125
|
+
result = update_service.run(resource: @resource, params: resource_params)
|
126
|
+
|
127
|
+
if result.valid?
|
128
|
+
render_edit_resource_form(disabled: disabled?(true))
|
129
|
+
else
|
130
|
+
render_edit_resource_form(disabled: disabled?(false))
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def render_edit_resource_form(disabled: true)
|
135
|
+
respond_to do |format|
|
136
|
+
format.html do
|
137
|
+
render turbo_stream: turbo_stream.replace(@resource.form_id, edit_form_component_instance(disabled?(disabled)))
|
138
|
+
end
|
139
|
+
format.turbo_stream do
|
140
|
+
render turbo_stream: turbo_stream.replace(@resource.form_id, edit_form_component_instance(disabled?(disabled)))
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def render_new_resource_form(resource)
|
146
|
+
respond_to do |format|
|
147
|
+
format.html do
|
148
|
+
render new_form_component_instance(resource)
|
149
|
+
end
|
150
|
+
format.turbo_stream do
|
151
|
+
render turbo_stream: turbo_stream.replace(context_params.frame, new_form_component_instance(resource))
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def bulk_action
|
157
|
+
ids = JSON.parse(params[:ids])
|
158
|
+
|
159
|
+
# Unscoped is needed to get the resources that are not deleted, archived, etc.
|
160
|
+
# It should be ok, since we control the ids in the frontend
|
161
|
+
@resources = resource_class.unscoped.where(id: ids)
|
162
|
+
authorize! :edit, @resources
|
163
|
+
|
164
|
+
bulk_processor = "#{params[:processor].gsub('-', '/').camelize}::Processor".constantize.new(@resources, params)
|
165
|
+
result = bulk_processor.perform
|
166
|
+
|
167
|
+
redirect_to_path result.path and return if result.result == :redirect
|
168
|
+
|
169
|
+
flash[result.result] = FlexiAdmin::Models::Toast.new(result.message)
|
170
|
+
|
171
|
+
reload_page
|
172
|
+
end
|
173
|
+
|
174
|
+
def autocomplete(includes: nil)
|
175
|
+
base_query = resource_class.with_parent(parent_instance)
|
176
|
+
.fulltext(params[:q])
|
177
|
+
base_query = base_query.includes(includes) if includes.present?
|
178
|
+
results_count = base_query.count
|
179
|
+
results = base_query.limit(100)
|
180
|
+
|
181
|
+
render FlexiAdmin::Components::Shared::Autocomplete::ResultsComponent.new(results:,
|
182
|
+
results_count:,
|
183
|
+
context_params:), layout: false
|
184
|
+
end
|
185
|
+
|
186
|
+
def datalist
|
187
|
+
results = resource_class.fulltext(params[:q])
|
188
|
+
.limit(100)
|
189
|
+
.order(*context_params.params[:ac_fields].map(&:to_sym))
|
190
|
+
.pluck(*context_params.params[:ac_fields].map(&:to_sym))
|
191
|
+
.uniq
|
192
|
+
render FlexiAdmin::Components::Shared::Autocomplete::ResultsComponent.new(results:,
|
193
|
+
context_params:), layout: false
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
def parent_instance
|
199
|
+
@parent_instance ||= locate_resource(context_params.parent)
|
200
|
+
end
|
201
|
+
|
202
|
+
def edit_form_component_instance(disabled)
|
203
|
+
[FlexiAdmin::NAMESPACE, "#{@resource.class.name}::Show::EditFormComponent"].join("::").constantize.new(@resource, disabled: disabled?(disabled))
|
204
|
+
end
|
205
|
+
|
206
|
+
def new_form_component_instance(resource)
|
207
|
+
"#{resource.class.name}::NewFormComponent".constantize.new(resource, parent: parent_instance)
|
208
|
+
end
|
209
|
+
|
210
|
+
def locate_resource(encoded_gid)
|
211
|
+
return nil if encoded_gid.blank?
|
212
|
+
|
213
|
+
gid = URI.decode_www_form_component(encoded_gid)
|
214
|
+
resource = GlobalID::Locator.locate(gid)
|
215
|
+
|
216
|
+
raise ActiveRecord::RecordNotFound, "Resource not found: #{encoded_gid}" if resource.blank?
|
217
|
+
|
218
|
+
resource
|
219
|
+
end
|
220
|
+
|
221
|
+
def resource_class
|
222
|
+
controller_name.classify.constantize
|
223
|
+
end
|
224
|
+
|
225
|
+
def fa_sorted?
|
226
|
+
fa_sort.present? && fa_order.present? && fa_order != "default"
|
227
|
+
end
|
228
|
+
|
229
|
+
def fa_sort
|
230
|
+
context_params[:sort]
|
231
|
+
end
|
232
|
+
|
233
|
+
def fa_order
|
234
|
+
context_params[:order]
|
235
|
+
end
|
236
|
+
|
237
|
+
def disabled?(form_disabled = false)
|
238
|
+
!current_ability&.can?(:update, resource_class) || form_disabled
|
239
|
+
end
|
240
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlexiAdmin
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
isolate_namespace FlexiAdmin
|
6
|
+
|
7
|
+
initializer "flexi_admin.assets" do |app|
|
8
|
+
app.config.assets.precompile += %w[flexi_admin_main.scss flexi_admin.js]
|
9
|
+
app.config.assets.paths << root.join("app/flexi_admin/javascript")
|
10
|
+
end
|
11
|
+
|
12
|
+
initializer "flexi_admin.helpers" do
|
13
|
+
ActiveSupport.on_load(:action_controller) do
|
14
|
+
include FlexiAdmin::Helpers::ApplicationHelper
|
15
|
+
end
|
16
|
+
|
17
|
+
ActiveSupport.on_load(:view_component) do
|
18
|
+
include Rails.application.routes.url_helpers
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# initializer "flexi_admin.stimulus_controllers" do |app|
|
23
|
+
# app.config.stimulus_modules |= [
|
24
|
+
# { name: "flexi-admin", path: "flexi_admin/controllers" }
|
25
|
+
# ]
|
26
|
+
# end
|
27
|
+
|
28
|
+
config.to_prepare do
|
29
|
+
Dir.glob(Engine.root.join("app", "**", "*_decorator*.rb")).each do |c|
|
30
|
+
require_dependency(c)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|