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.
Files changed (127) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +42 -0
  3. data/Rakefile +7 -0
  4. data/lib/flexi_admin/components/actions/checkbox_component.html.slim +8 -0
  5. data/lib/flexi_admin/components/actions/checkbox_component.rb +13 -0
  6. data/lib/flexi_admin/components/actions/select_component.html.slim +11 -0
  7. data/lib/flexi_admin/components/actions/select_component.rb +17 -0
  8. data/lib/flexi_admin/components/base_component.rb +19 -0
  9. data/lib/flexi_admin/components/form/field_component.rb +11 -0
  10. data/lib/flexi_admin/components/form/label_component.html.slim +2 -0
  11. data/lib/flexi_admin/components/form/label_component.rb +13 -0
  12. data/lib/flexi_admin/components/form/rows_component.rb +9 -0
  13. data/lib/flexi_admin/components/form/text_input_component.html.slim +5 -0
  14. data/lib/flexi_admin/components/form/text_input_component.rb +17 -0
  15. data/lib/flexi_admin/components/helpers/action_button_helper.rb +28 -0
  16. data/lib/flexi_admin/components/helpers/action_helper.rb +12 -0
  17. data/lib/flexi_admin/components/helpers/icon_helper.rb +11 -0
  18. data/lib/flexi_admin/components/helpers/link_helper.rb +8 -0
  19. data/lib/flexi_admin/components/helpers/resource_helper.rb +71 -0
  20. data/lib/flexi_admin/components/helpers/selectable.rb +11 -0
  21. data/lib/flexi_admin/components/helpers/url_helper.rb +8 -0
  22. data/lib/flexi_admin/components/helpers/value_formatter.rb +32 -0
  23. data/lib/flexi_admin/components/nav/floating_toc_component.html.slim +2 -0
  24. data/lib/flexi_admin/components/nav/floating_toc_component.rb +6 -0
  25. data/lib/flexi_admin/components/resource/autocomplete_component.html.slim +30 -0
  26. data/lib/flexi_admin/components/resource/autocomplete_component.rb +83 -0
  27. data/lib/flexi_admin/components/resource/button_select_component.html.slim +13 -0
  28. data/lib/flexi_admin/components/resource/button_select_component.rb +19 -0
  29. data/lib/flexi_admin/components/resource/form_component.rb +18 -0
  30. data/lib/flexi_admin/components/resource/form_element_component.html.slim +3 -0
  31. data/lib/flexi_admin/components/resource/form_element_component.rb +31 -0
  32. data/lib/flexi_admin/components/resource/form_mixin.rb +287 -0
  33. data/lib/flexi_admin/components/resource/link_action_component.html.slim +8 -0
  34. data/lib/flexi_admin/components/resource/link_action_component.rb +16 -0
  35. data/lib/flexi_admin/components/resource/show_page_component.rb +21 -0
  36. data/lib/flexi_admin/components/resource/view_component.html.slim +26 -0
  37. data/lib/flexi_admin/components/resource/view_component.rb +22 -0
  38. data/lib/flexi_admin/components/resources/bulk_action/button_component.html.slim +7 -0
  39. data/lib/flexi_admin/components/resources/bulk_action/button_component.rb +29 -0
  40. data/lib/flexi_admin/components/resources/bulk_action/modal_component.html.slim +32 -0
  41. data/lib/flexi_admin/components/resources/bulk_action/modal_component.rb +54 -0
  42. data/lib/flexi_admin/components/resources/grid_view/card_component.html.slim +18 -0
  43. data/lib/flexi_admin/components/resources/grid_view/card_component.rb +65 -0
  44. data/lib/flexi_admin/components/resources/grid_view/grid_component.html.slim +10 -0
  45. data/lib/flexi_admin/components/resources/grid_view/grid_component.rb +16 -0
  46. data/lib/flexi_admin/components/resources/grid_view_component.rb +89 -0
  47. data/lib/flexi_admin/components/resources/index_page_component.html.slim +13 -0
  48. data/lib/flexi_admin/components/resources/index_page_component.rb +19 -0
  49. data/lib/flexi_admin/components/resources/list_view/cell_component.html.slim +2 -0
  50. data/lib/flexi_admin/components/resources/list_view/cell_component.rb +26 -0
  51. data/lib/flexi_admin/components/resources/list_view/table_component.html.slim +17 -0
  52. data/lib/flexi_admin/components/resources/list_view/table_component.rb +21 -0
  53. data/lib/flexi_admin/components/resources/list_view_component.rb +80 -0
  54. data/lib/flexi_admin/components/resources/pagination_component.html.slim +42 -0
  55. data/lib/flexi_admin/components/resources/pagination_component.rb +64 -0
  56. data/lib/flexi_admin/components/resources/resources_component.rb +34 -0
  57. data/lib/flexi_admin/components/resources/switch_view_component.html.slim +16 -0
  58. data/lib/flexi_admin/components/resources/switch_view_component.rb +45 -0
  59. data/lib/flexi_admin/components/resources/view_component.html.slim +12 -0
  60. data/lib/flexi_admin/components/resources/view_component.rb +15 -0
  61. data/lib/flexi_admin/components/shared/alert_component.html.slim +2 -0
  62. data/lib/flexi_admin/components/shared/alert_component.rb +11 -0
  63. data/lib/flexi_admin/components/shared/autocomplete/results_component.html.slim +15 -0
  64. data/lib/flexi_admin/components/shared/autocomplete/results_component.rb +50 -0
  65. data/lib/flexi_admin/components/shared/autocomplete.rb +6 -0
  66. data/lib/flexi_admin/components/shared/datalist_component.html.slim +24 -0
  67. data/lib/flexi_admin/components/shared/datalist_component.rb +20 -0
  68. data/lib/flexi_admin/components/shared/link_component.html.slim +3 -0
  69. data/lib/flexi_admin/components/shared/link_component.rb +15 -0
  70. data/lib/flexi_admin/components/shared/medium_component.html.slim +7 -0
  71. data/lib/flexi_admin/components/shared/medium_component.rb +51 -0
  72. data/lib/flexi_admin/components/shared/table/header_item_component.html.slim +9 -0
  73. data/lib/flexi_admin/components/shared/table/header_item_component.rb +78 -0
  74. data/lib/flexi_admin/components/shared/trix_component.html.slim +22 -0
  75. data/lib/flexi_admin/components/shared/trix_component.rb +21 -0
  76. data/lib/flexi_admin/components.rb +87 -0
  77. data/lib/flexi_admin/config.rb +24 -0
  78. data/lib/flexi_admin/controllers/modals_controller.rb +13 -0
  79. data/lib/flexi_admin/controllers/resources_controller.rb +240 -0
  80. data/lib/flexi_admin/controllers.rb +9 -0
  81. data/lib/flexi_admin/engine.rb +34 -0
  82. data/lib/flexi_admin/helpers/application_helper.rb +4 -0
  83. data/lib/flexi_admin/helpers.rb +8 -0
  84. data/lib/flexi_admin/javascript/controllers/application.js +9 -0
  85. data/lib/flexi_admin/javascript/controllers/autocomplete_controller.js +142 -0
  86. data/lib/flexi_admin/javascript/controllers/bulk_action_controller.js +158 -0
  87. data/lib/flexi_admin/javascript/controllers/button_select_controller.js +32 -0
  88. data/lib/flexi_admin/javascript/controllers/datalist_controller.js +104 -0
  89. data/lib/flexi_admin/javascript/controllers/floating_toc_controller.js +39 -0
  90. data/lib/flexi_admin/javascript/controllers/form_controller.js +17 -0
  91. data/lib/flexi_admin/javascript/controllers/form_validation_controller.js +86 -0
  92. data/lib/flexi_admin/javascript/controllers/index.js +44 -0
  93. data/lib/flexi_admin/javascript/controllers/pagination_controller.js +13 -0
  94. data/lib/flexi_admin/javascript/controllers/sorting_controller.js +17 -0
  95. data/lib/flexi_admin/javascript/controllers/switch_view_controller.js +15 -0
  96. data/lib/flexi_admin/javascript/controllers/toast_controller.js +18 -0
  97. data/lib/flexi_admin/javascript/controllers/trix_controller.js +32 -0
  98. data/lib/flexi_admin/javascript/controllers/uploads_controller.js +164 -0
  99. data/lib/flexi_admin/javascript/flexi_admin.js +4 -0
  100. data/lib/flexi_admin/javascript/utils.js +26 -0
  101. data/lib/flexi_admin/models/concerns/application_resource.rb +25 -0
  102. data/lib/flexi_admin/models/concerns/parentable.rb +17 -0
  103. data/lib/flexi_admin/models/context_params.rb +127 -0
  104. data/lib/flexi_admin/models/resources/context.rb +59 -0
  105. data/lib/flexi_admin/models/struct.rb +29 -0
  106. data/lib/flexi_admin/models/toast.rb +23 -0
  107. data/lib/flexi_admin/models.rb +20 -0
  108. data/lib/flexi_admin/prompts/codegen-system-prompt.md +50 -0
  109. data/lib/flexi_admin/railtie.rb +78 -0
  110. data/lib/flexi_admin/routes.rb +15 -0
  111. data/lib/flexi_admin/services/code_gen/code_export.rb +22 -0
  112. data/lib/flexi_admin/services/code_gen/gemini.rb +104 -0
  113. data/lib/flexi_admin/services/code_gen/gpt.rb +68 -0
  114. data/lib/flexi_admin/services/code_gen/runner.rb +210 -0
  115. data/lib/flexi_admin/services/code_gen.rb +14 -0
  116. data/lib/flexi_admin/services/create_resource.rb +32 -0
  117. data/lib/flexi_admin/services/update_resource.rb +30 -0
  118. data/lib/flexi_admin/services.rb +10 -0
  119. data/lib/flexi_admin/version.rb +10 -0
  120. data/lib/flexi_admin/views/shared/_redirect.slim +2 -0
  121. data/lib/flexi_admin/views/shared/_reload.slim +2 -0
  122. data/lib/flexi_admin/views/shared/_toasts.slim +15 -0
  123. data/lib/flexi_admin/views/shared/not_authorized.slim +11 -0
  124. data/lib/flexi_admin.rb +58 -0
  125. data/lib/tasks/flexi_admin.rake +49 -0
  126. data/lib/tasks/semantic.rake +57 -0
  127. metadata +333 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f7899a2bba48f2ff003b6b90de70a6df1b61a05fc37e07dc47e07f4d3a3a9cc7
4
+ data.tar.gz: c22ed4d803e860e4b250ac55670737c5df158705d3b5c3dd0d425646b4155adf
5
+ SHA512:
6
+ metadata.gz: 2d80c1451c28a1d842e2eb24660f5489184bb403a1eec4eb740eeda5f7eb11d3592ddd9a4cc9f80866664af28552aaaf2f70f07ddab18ca635fa551106f56f0e
7
+ data.tar.gz: 7677d9ab7f7fdc1980066ec248e52725db1f4b017a1baaf0ae700cdb69f9cd06d81bdeee9271f51ab86617459aa278e433077f4cb56a65bea23f509e7bfb5f38
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # FlexiAdmin Rails
2
+
3
+ Steps required to get FlexiAdmin working with a Rails app:
4
+
5
+ **Gemfile**
6
+
7
+ 1. add `gem 'flexi_admin', git: 'https://github.com/landovsky/flexi_admin.git', branch: 'main'` to the `Gemfile`
8
+
9
+ **Stylesheets**
10
+
11
+ 2. add `@import "flexi_admin.scss";` to the `app/assets/stylesheets/application.scss` file
12
+
13
+ **JavaScript**
14
+
15
+ 3. add `import "flexi_admin";` to the `app/javascript/application.js` file
16
+
17
+ # Temporary (workaround) requirements
18
+
19
+ - can't get stylesheets to load from gem, so adding to host app:
20
+
21
+ ```scss
22
+ // Production
23
+ // @import "flexi_admin.scss";
24
+ // Local dev
25
+ // @import "../../flexi_admin/app/assets/stylesheets/flexi_admin";
26
+ ```
27
+
28
+ - add modals controller:
29
+
30
+ ```
31
+ # frozen_string_literal: true
32
+
33
+ class ModalsController < AdminController
34
+ include FlexiAdmin::Controllers::ModalsController
35
+ end
36
+ ```
37
+
38
+ ```ruby
39
+ resources :modals, only: [] do
40
+ get :show, on: :collection
41
+ end
42
+ ```
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake"
5
+
6
+ # Load all rake tasks from lib/tasks
7
+ Dir.glob('lib/tasks/**/*.rake').each { |r| load r }
@@ -0,0 +1,8 @@
1
+ .form-check.bulk-action-checkbox
2
+ input [class="form-check-input"
3
+ type="checkbox"
4
+ value="#{id}"
5
+ id="checkbox-#{id}"
6
+ name="#{scope}"
7
+ data-action="#{select_all ? 'change->bulk-action#toggleAll' : 'change->bulk-action#toggle'}"]
8
+ = content
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Actions
4
+ class CheckboxComponent < FlexiAdmin::Components::BaseComponent
5
+ attr_reader :id, :scope, :select_all
6
+
7
+ def initialize(id:, scope:, select_all: false)
8
+ @id = id
9
+ @scope = scope
10
+ @select_all = select_all
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ div data-bulk-action-scope-value="#{scope}"
2
+ .dropdown
3
+ button.btn.btn-outline-secondary.dropdown-toggle [type="button"
4
+ data-bs-toggle="dropdown"
5
+ aria-expanded="false"
6
+ aria-haspopup="true"]
7
+ | Akce
8
+ ul.dropdown-menu
9
+ - actions.each do |action|
10
+ li
11
+ = action
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Actions
4
+ class SelectComponent < FlexiAdmin::Components::BaseComponent
5
+ attr_reader :scope, :label
6
+
7
+ renders_many :actions
8
+
9
+ def initialize(context: nil, scope: nil, label: "Akce")
10
+ @context = context
11
+ @scope = scope || context&.scope
12
+ @label = label
13
+
14
+ raise ArgumentError, "context or scope is required" if context.blank? && scope.blank?
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin
4
+ module Components
5
+ class BaseComponent < ViewComponent::Base
6
+ include FlexiAdmin::Helpers::ApplicationHelper
7
+
8
+ # Delegate main_app to view context
9
+ delegate :main_app, to: :helpers
10
+
11
+ # def render(*args)
12
+ # super(*args)
13
+ # rescue StandardError => e
14
+ # binding.pry if Rails.env.development? && !defined?(@@once)
15
+ # @@once = true
16
+ # end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "view_component"
4
+
5
+ module FlexiAdmin::Components::Form
6
+ class FieldComponent < FlexiAdmin::Components::BaseComponent
7
+ def call
8
+ content_tag :div, content, class: "field-wrapper relative flex flex-col grow pb-2 md:pb-0 leading-tight min-h-14 h-full field-wrapper-layout-inline md:flex-row md:items-center field-wrapper-size-regular field-width-regular"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,2 @@
1
+ div class="pt-4 flex self-start items-center flex-shrink-0 px-6 uppercase font-semibold text-gray-500 text-sm h-full md:pt-0 md:h-14" style="width: 30%"
2
+ = form.label name, **options
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Form
4
+ class LabelComponent < FlexiAdmin::Components::BaseComponent
5
+ attr_reader :form, :name, :options
6
+
7
+ def initialize(form, name, options = {})
8
+ @form = form
9
+ @name = name
10
+ @options = options
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Form
4
+ class RowsComponent < FlexiAdmin::Components::BaseComponent
5
+ def call
6
+ content_tag :div, content, class: "divide-y overflow-auto"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ // Input column
2
+ div.flex-1.flex.flex-row.md:min-h-inherit.py-2.px-6
3
+ // Input wrapper
4
+ div.self-center.w-full.has-sidebar:w-full
5
+ = form.text_field name, class: input_classes, **options
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Form
4
+ class TextInputComponent < FlexiAdmin::Components::BaseComponent
5
+ attr_reader :form, :name, :options
6
+
7
+ def initialize(form, name, options = {})
8
+ @form = form
9
+ @name = name
10
+ @options = options
11
+ end
12
+
13
+ def input_classes
14
+ "appearance-none inline-flex bg-gray-25 disabled:cursor-not-allowed text-gray-600 disabled:opacity-50 rounded py-2 px-3 leading-tight border focus:border-gray-600 focus-visible:ring-0 focus:text-gray-700 placeholder:text-gray-300 border-gray-200 w-full"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Helpers::ActionButtonHelper
4
+ def button(label, icon: nil)
5
+ @button = label
6
+ @button_icon = icon
7
+ end
8
+
9
+ def button_text
10
+ @button
11
+ end
12
+
13
+ def button_icon
14
+ @button_icon
15
+ end
16
+
17
+ def button_icon_class
18
+ "bi-#{button_icon}"
19
+ end
20
+
21
+ def title(title)
22
+ @title = title
23
+ end
24
+
25
+ def title_text
26
+ @title
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Helpers::ActionHelper
4
+ # Context overrides the context normally given by the class including this module
5
+ # Example - adding action button to a custom view form
6
+ def action(action_component, disabled: true, selection_dependent: true, context: nil)
7
+ render FlexiAdmin::Components::Resources::BulkAction::ButtonComponent.new(context || self.context,
8
+ action_component,
9
+ disabled:,
10
+ selection_dependent:)
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Helpers::IconHelper
4
+ def icon
5
+ self.class.instance_variable_get(:@icon_value) || options[:icon]
6
+ end
7
+
8
+ def icon_class
9
+ "bi-#{icon}" if icon.present?
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Helpers::LinkHelper
4
+ def navigate_to(title, resource)
5
+ helpers.link_to title, [:admin, resource], "data-turbo-frame": "_top"
6
+ # content_tag(:a, title, href: resource, "data-turbo-frame": "_top")
7
+ end
8
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Helpers::ResourceHelper
4
+ include FlexiAdmin::Components::Helpers::UrlHelper
5
+
6
+ def autocomplete_path(action:, fields:, parent: nil)
7
+ payload = {
8
+ ac_action: action,
9
+ ac_path: resource__path,
10
+ fa_parent: parent&.gid_param,
11
+ ac_fields: fields
12
+ }
13
+ main_app.send("autocomplete_admin_#{scope_plural}_path", params: payload)
14
+ end
15
+
16
+ def datalist_path(action:, fields:, parent: nil)
17
+ payload = {
18
+ ac_action: action,
19
+ ac_fields: fields
20
+ }
21
+
22
+ main_app.send("datalist_admin_#{scope_plural}_path", params: payload)
23
+ end
24
+
25
+ def edit_resource_path(resource, **params)
26
+ main_app.send("edit_admin_#{scope_singular}_path", resource, params:)
27
+ end
28
+
29
+ def bulk_action_path(scope, **params)
30
+ raise 'Scope is not defined' if scope.blank?
31
+
32
+ main_app.send("bulk_action_admin_#{scope}_path", params:)
33
+ end
34
+
35
+ def resource_path(resource, **params)
36
+ main_app.send("admin_#{scope_singular}_path", resource, params:)
37
+ end
38
+
39
+ def resource__path
40
+ "admin_#{scope_singular}_path"
41
+ end
42
+
43
+ def resources_path(**params)
44
+ main_app.send("admin_#{scope_plural}_path", params:)
45
+ end
46
+
47
+ def resource_input_name
48
+ "#{scope_singular}_id"
49
+ end
50
+
51
+ def scope_plural
52
+ scope.gsub('/', '_')
53
+ end
54
+
55
+ def scope_singular
56
+ scope.singularize
57
+ end
58
+
59
+ def scope
60
+ @scope ||= begin
61
+ return context.scope if defined?(context)
62
+ return resource.model_name.try(:plural) if defined?(resource)
63
+
64
+ raise 'Scope is not defined'
65
+ end
66
+ end
67
+
68
+ def paginate(resource, per_page: 10)
69
+ resource.paginate(page: params[:page], per_page:)
70
+ end
71
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Helpers::Selectable
4
+ def selectable
5
+ @is_selectable = true
6
+ end
7
+
8
+ def selectable?
9
+ @is_selectable
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "action_view"
4
+
5
+ module FlexiAdmin::Components::Helpers::UrlHelper
6
+ include ::ActionView::Helpers::UrlHelper
7
+ include ::ActionView::RoutingUrlFor
8
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Helpers::ValueFormatter
4
+
5
+ def as_text(value)
6
+ value.to_s
7
+ end
8
+
9
+ def as_date(value, format: nil)
10
+ return nil if value.blank?
11
+
12
+ I18n.l(value, format:)
13
+ end
14
+
15
+ def as_navigation(value)
16
+ helpers.link_to value, value, 'data-turbo-frame': '_top'
17
+ # content_tag(:a, value, href: value, 'data-turbo-frame': '_top')
18
+ end
19
+
20
+ def format(formatter)
21
+ case formatter.to_sym
22
+ when :date
23
+ proc { |value| as_date(value) }
24
+ when :text
25
+ proc { |value| as_text(value) }
26
+ when :navigation
27
+ proc { |value| as_navigation(value) }
28
+ else
29
+ raise ArgumentError, "Unknown formatter: #{@formatter}"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,2 @@
1
+ nav.navbar.sticky-top.bg-white data-controller="floating-toc"
2
+ ul.nav.nav-pills.mb-2.mb-lg-0 data-floating-toc-target="toc"
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Nav
4
+ class FloatingTocComponent < FlexiAdmin::Components::BaseComponent
5
+ end
6
+ end
@@ -0,0 +1,30 @@
1
+ .autocomplete [data-controller="#{ disabled ? '' : 'autocomplete' }"]
2
+ - if disabled && data_list?
3
+ = value
4
+ - elsif disabled && !data_list?
5
+ a href="#{resource_path(resource)}" data-turbo-frame="_top" = resource&.ac_title
6
+ /= helpers.link_to resource&.ac_title, resource_path(resource), data: { turbo_frame: '_top' }
7
+ - else
8
+ .input-group style="width: #{width || '100%'}"
9
+ .input-group-text id="button-addon1"
10
+ i.bi class="#{icon_class}"
11
+
12
+ = text_field_tag name, resource&.ac_title,
13
+ class: 'form-control',
14
+ placeholder: 'hledat',
15
+ 'aria-describedby': 'button-addon1',
16
+ value: ,
17
+ required:,
18
+ **autocomplete_options
19
+ .invalid-feedback.d-none
20
+ - if select?
21
+ input [type="hidden"
22
+ name="#{name}"
23
+ data-autocomplete-target="resourceId"
24
+ value="#{resource&.id}"]
25
+ .clear-icon.d-none data-autocomplete-target="clearIcon" data-action="click->autocomplete#clear"
26
+ i.bi.bi-x-circle.me-2
27
+ .loading-icon.d-none data-autocomplete-target="loadingIcon"
28
+ .icon
29
+
30
+ ul.collapse.show data-autocomplete-target="list"
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Independent component.
4
+ module FlexiAdmin::Components::Resource
5
+ class AutocompleteComponent < FlexiAdmin::Components::BaseComponent
6
+ include FlexiAdmin::Components::Helpers::ResourceHelper
7
+
8
+ attr_reader :resource, :disabled, :action, :parent, :fields, :required,
9
+ :name, :html_options, :path, :width, :value
10
+
11
+ def initialize(resource = nil, scope:, fields: [:title],
12
+ action: :select, parent: nil, path: nil,
13
+ value: nil, **html_options)
14
+ @resource = resource
15
+ @scope = scope
16
+ @parent = parent
17
+ @fields = fields
18
+ @path = path
19
+ @action = action
20
+ @value = value
21
+
22
+ @html_options = html_options
23
+ @width = html_options.delete(:width)
24
+ @required = html_options[:required]
25
+ @style = html_options.delete(:style)
26
+ @disabled = html_options.key?(:disabled) ? html_options[:disabled] : false
27
+ @name = html_options[:name] || resource_input_name
28
+
29
+ validate_action!
30
+ end
31
+
32
+ def autocomplete_options
33
+ {
34
+ style: 'border-top-right-radius: 0.4rem; border-bottom-right-radius: 0.4rem;',
35
+ data: { autocomplete_target: 'input',
36
+ action: 'keyup->autocomplete#keyup focusout->autocomplete#onFocusOut',
37
+ autocomplete_search_path: get_path,
38
+ autocomplete_is_disabled: disabled,
39
+ field_type: kind }.merge(html_options)
40
+ }
41
+ end
42
+
43
+ private
44
+
45
+ def icon_class
46
+ case action
47
+ when :input
48
+ 'bi-alphabet'
49
+ else
50
+ 'bi-search'
51
+ end
52
+ end
53
+
54
+ def select?
55
+ action == :select
56
+ end
57
+
58
+ def data_list?
59
+ action == :input
60
+ end
61
+
62
+ def kind
63
+ data_list? ? :text : :autocomplete
64
+ end
65
+
66
+ def get_path
67
+ return path if path.present?
68
+
69
+ case action
70
+ when :input
71
+ datalist_path(action: :input, parent:, fields:)
72
+ else
73
+ autocomplete_path(action:, parent:, fields:)
74
+ end
75
+ end
76
+
77
+ def validate_action!
78
+ return if %i[select show input].include?(@action)
79
+
80
+ raise "Invalid action: #{@action}"
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,13 @@
1
+ div.button-select data-controller="button-select" data-button-select-disabled-value="#{disabled}"
2
+ .btn-group
3
+ - if disabled
4
+ button.btn.btn-outline-secondary.text-nowrap data-value=value data-button-select-target="button" disabled=true
5
+ = value || '-'
6
+ - else
7
+ - options.each do |option|
8
+ button.btn.btn-outline-secondary.text-nowrap data-action="click->button-select#select" data-value=option data-button-select-target="button"
9
+ = option
10
+ = hidden_field_tag html_options[:name] || attr_name, value, data: { 'button-select-target': 'input' }
11
+ - if form
12
+ .invalid-feedback data-button-select-target="invalid-feedback"
13
+ = resource.errors[attr_name].first
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Requirement is handled by the model
4
+ module FlexiAdmin::Components::Resource
5
+ class ButtonSelectComponent < FlexiAdmin::Components::BaseComponent
6
+ attr_reader :resource, :attr_name, :options, :form, :label, :value, :html_options, :disabled
7
+
8
+ def initialize(resource, attr_name, options, form:, label: nil, value: nil, disabled: false, **html_options)
9
+ @resource = resource
10
+ @attr_name = attr_name
11
+ @options = options
12
+ @form = form
13
+ @label = label
14
+ @value = value
15
+ @html_options = html_options
16
+ @disabled = disabled
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Resource
4
+ class FormComponent < FlexiAdmin::Components::BaseComponent
5
+ include FlexiAdmin::Components::Resource::FormMixin
6
+
7
+ attr_reader :resource
8
+
9
+ def initialize(resource, disabled: true)
10
+ @resource = resource
11
+ @disabled = disabled
12
+ end
13
+
14
+ def disabled
15
+ !helpers.current_ability&.can?(:update, resource) || @disabled
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ turbo-frame id="#{resource.try(:form_id) || 'form_frame'}"
2
+ = form_tag(url, method: , id: form_id, class: css_class, data: merged_data, **html_options_except_data) do
3
+ = fields
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlexiAdmin::Components::Resource
4
+ class FormElementComponent < FlexiAdmin::Components::BaseComponent
5
+ include FlexiAdmin::Components::Helpers::ResourceHelper
6
+
7
+ renders_one :fields
8
+
9
+ attr_reader :resource, :url, :css_class, :method, :html_options_except_data, :merged_data
10
+
11
+ def initialize(resource, url:, css_class:, method: :post, **html_options)
12
+ @resource = resource
13
+ @url = url
14
+ @css_class = css_class
15
+ @method = method
16
+ data = html_options[:data] || {}
17
+ @merged_data = merge_data_keys(data)
18
+ @html_options_except_data = html_options.except(:data)
19
+ end
20
+
21
+ def form_id
22
+ resource.try(:identifier) || "form"
23
+ end
24
+
25
+ def merge_data_keys(data)
26
+ controller = data[:controller]
27
+ controllers = controller.present? ? [controller, "form-validation"] : ["form-validation"]
28
+ data.merge(controller: controllers.join(" "))
29
+ end
30
+ end
31
+ end