uchi 0.1.5 → 0.1.6
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 +4 -4
- data/app/assets/javascripts/uchi/application.js +2655 -24
- data/app/assets/javascripts/uchi.js +11 -0
- data/app/assets/stylesheets/uchi/application.css +982 -1311
- data/app/assets/tailwind/uchi.css +4 -4
- data/app/components/uchi/field/belongs_to/edit.html.erb +1 -1
- data/app/components/uchi/field/belongs_to/index.html.erb +1 -1
- data/app/components/uchi/field/belongs_to/show.html.erb +3 -5
- data/app/components/uchi/field/belongs_to.rb +30 -7
- data/app/components/uchi/field/boolean/edit.html.erb +1 -1
- data/app/components/uchi/field/date/edit.html.erb +1 -1
- data/app/components/uchi/field/date_time/edit.html.erb +1 -1
- data/app/components/uchi/field/file/edit.html.erb +1 -1
- data/app/components/uchi/field/file/index.html.erb +2 -1
- data/app/components/uchi/field/file/show.html.erb +3 -2
- data/app/components/uchi/field/has_and_belongs_to_many/show.html.erb +5 -3
- data/app/components/uchi/field/has_many/show.html.erb +5 -3
- data/app/components/uchi/field/id/index.html.erb +1 -1
- data/app/components/uchi/field/id/show.html.erb +1 -1
- data/app/components/uchi/field/image/edit.html.erb +1 -1
- data/app/components/uchi/field/image/index.html.erb +2 -1
- data/app/components/uchi/field/image/show.html.erb +2 -1
- data/app/components/uchi/field/number/edit.html.erb +1 -1
- data/app/components/uchi/field/string/edit.html.erb +1 -1
- data/app/components/uchi/field/text/edit.html.erb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/breadcrumb.rb +5 -5
- data/app/components/{flowbite → uchi/flowbite}/breadcrumb_home.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/breadcrumb_item/current.rb +3 -3
- data/app/components/{flowbite → uchi/flowbite}/breadcrumb_item/first.rb +4 -4
- data/app/components/{flowbite → uchi/flowbite}/breadcrumb_item.rb +4 -4
- data/app/components/{flowbite → uchi/flowbite}/breadcrumb_separator.rb +7 -5
- data/app/components/uchi/flowbite/button/outline.rb +37 -0
- data/app/components/uchi/flowbite/button/pill.rb +40 -0
- data/app/components/uchi/flowbite/button.rb +93 -0
- data/app/components/uchi/flowbite/card/card.html.erb +7 -0
- data/app/components/uchi/flowbite/card/title.rb +37 -0
- data/app/components/uchi/flowbite/card.rb +84 -0
- data/app/components/{flowbite → uchi/flowbite}/input/checkbox.rb +7 -7
- data/app/components/{flowbite → uchi/flowbite}/input/date.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input/date_time.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input/email.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input/field.rb +11 -10
- data/app/components/uchi/flowbite/input/file.rb +30 -0
- data/app/components/{flowbite → uchi/flowbite}/input/hint.rb +6 -5
- data/app/components/{flowbite → uchi/flowbite}/input/label.rb +8 -7
- data/app/components/{flowbite → uchi/flowbite}/input/number.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input/password.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input/phone.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input/radio_button.rb +7 -7
- data/app/components/{flowbite → uchi/flowbite}/input/select.rb +16 -7
- data/app/components/uchi/flowbite/input/textarea.rb +42 -0
- data/app/components/{flowbite → uchi/flowbite}/input/url.rb +1 -1
- data/app/components/uchi/flowbite/input/validation_error.rb +39 -0
- data/app/components/uchi/flowbite/input_field/checkbox.html.erb +9 -0
- data/app/components/{flowbite → uchi/flowbite}/input_field/checkbox.rb +10 -6
- data/app/components/{flowbite → uchi/flowbite}/input_field/date.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field/date_time.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field/email.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field/file.rb +2 -2
- data/app/components/uchi/flowbite/input_field/input_field.html.erb +9 -0
- data/app/components/{flowbite → uchi/flowbite}/input_field/number.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field/password.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field/phone.rb +2 -2
- data/app/components/uchi/flowbite/input_field/radio_button.html.erb +9 -0
- data/app/components/{flowbite → uchi/flowbite}/input_field/radio_button.rb +13 -9
- data/app/components/{flowbite → uchi/flowbite}/input_field/select.rb +7 -3
- data/app/components/{flowbite → uchi/flowbite}/input_field/text.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/input_field/textarea.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field/url.rb +2 -2
- data/app/components/{flowbite → uchi/flowbite}/input_field.rb +19 -5
- data/app/components/uchi/flowbite/link.rb +41 -0
- data/app/components/{flowbite → uchi/flowbite}/style.rb +1 -1
- data/app/components/{flowbite → uchi/flowbite}/toast/icon.rb +1 -1
- data/app/components/uchi/flowbite/toast/toast.html.erb +40 -0
- data/app/components/{flowbite → uchi/flowbite}/toast.rb +2 -2
- data/app/components/uchi/ui/actions/dropdown/dropdown.html.erb +59 -0
- data/app/components/uchi/ui/actions/dropdown.rb +32 -0
- data/app/components/uchi/ui/breadcrumb/breadcrumb.html.erb +4 -4
- data/app/components/uchi/ui/form/input/collection_checkboxes.html.erb +2 -1
- data/app/components/uchi/ui/form/input/collection_checkboxes.rb +12 -17
- data/app/components/uchi/ui/frame/frame.html.erb +6 -1
- data/app/components/uchi/ui/index/records_table/records_table.html.erb +109 -18
- data/app/components/uchi/ui/index/records_table/search_form/search_form.html.erb +21 -5
- data/app/components/uchi/ui/navigation/navigation.html.erb +9 -0
- data/app/components/uchi/ui/navigation.rb +37 -0
- data/app/components/uchi/ui/no_value/no_value.html.erb +1 -0
- data/app/components/uchi/ui/no_value.rb +8 -0
- data/app/components/uchi/ui/page_header/page_header.html.erb +7 -2
- data/app/components/uchi/ui/pagination/current_link.html.erb +1 -1
- data/app/components/uchi/ui/pagination/gap.html.erb +7 -1
- data/app/components/uchi/ui/pagination/link.html.erb +1 -1
- data/app/components/uchi/ui/pagination/next_link.html.erb +18 -3
- data/app/components/uchi/ui/pagination/pagination.html.erb +3 -1
- data/app/components/uchi/ui/pagination/previous_link.html.erb +18 -3
- data/app/components/uchi/ui/pagination.rb +1 -1
- data/app/components/uchi/ui/show/attribute_fields/attribute_fields.html.erb +4 -3
- data/app/components/uchi/ui/spinner/spinner.html.erb +17 -3
- data/app/controllers/uchi/actions/executions_controller.rb +107 -0
- data/app/controllers/uchi/repository_controller.rb +21 -1
- data/app/views/layouts/uchi/_flash_messages.html.erb +1 -1
- data/app/views/layouts/uchi/application.html.erb +10 -16
- data/app/views/uchi/navigation/_main.html.erb +9 -0
- data/app/views/uchi/repository/edit.html.erb +2 -2
- data/app/views/uchi/repository/index.html.erb +12 -3
- data/app/views/uchi/repository/new.html.erb +2 -2
- data/app/views/uchi/repository/show.html.erb +13 -2
- data/lib/generators/uchi/controller/templates/controller.rb.tt +0 -5
- data/lib/generators/uchi/scaffold/scaffold_generator.rb +15 -0
- data/lib/uchi/action.rb +84 -0
- data/lib/uchi/action_response.rb +108 -0
- data/lib/uchi/repository/translate.rb +14 -0
- data/lib/uchi/repository.rb +25 -0
- data/lib/uchi/version.rb +1 -1
- data/lib/uchi.rb +2 -0
- metadata +63 -50
- data/app/components/flowbite/button/outline.rb +0 -22
- data/app/components/flowbite/button/pill.rb +0 -40
- data/app/components/flowbite/button.rb +0 -92
- data/app/components/flowbite/card.rb +0 -45
- data/app/components/flowbite/input/file.rb +0 -30
- data/app/components/flowbite/input/textarea.rb +0 -42
- data/app/components/flowbite/input/validation_error.rb +0 -11
- data/app/components/flowbite/input_field/checkbox.html.erb +0 -14
- data/app/components/flowbite/input_field/input_field.html.erb +0 -8
- data/app/components/flowbite/input_field/radio_button.html.erb +0 -14
- data/app/components/flowbite/link.rb +0 -21
- data/app/components/flowbite/toast/toast.html.erb +0 -11
- /data/app/components/{flowbite → uchi/flowbite}/toast/icon.html.erb +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<div class="<%= classes.join(" ") %>">
|
|
2
|
+
<div class="flex items-center h-5"><%= input %></div>
|
|
3
|
+
|
|
4
|
+
<div class="ms-2 text-sm"><%= label %><%= hint %></div>
|
|
5
|
+
|
|
6
|
+
<% errors.each do |error| %>
|
|
7
|
+
<%= render(Uchi::Flowbite::Input::ValidationError.new) { error.upcase_first } %>
|
|
8
|
+
<% end %>
|
|
9
|
+
</div>
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module Flowbite
|
|
3
|
+
module Uchi::Flowbite
|
|
4
4
|
class InputField
|
|
5
5
|
class RadioButton < InputField
|
|
6
|
-
def initialize(attribute:, form:, value:, disabled: false, hint: nil, input: {}, label: {})
|
|
7
|
-
super(attribute: attribute, form: form, disabled: disabled, hint: hint, input: input, label: label)
|
|
6
|
+
def initialize(attribute:, form:, value:, class: nil, disabled: false, hint: nil, input: {}, label: {}, options: {})
|
|
7
|
+
super(attribute: attribute, class: binding.local_variable_get(:class), form: form, disabled: disabled, hint: hint, input: input, label: label, options: options)
|
|
8
8
|
@value = value
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
protected
|
|
12
12
|
|
|
13
|
+
def default_container_classes
|
|
14
|
+
["flex"]
|
|
15
|
+
end
|
|
16
|
+
|
|
13
17
|
def default_input
|
|
14
18
|
args = {
|
|
15
19
|
attribute: @attribute,
|
|
@@ -37,7 +41,7 @@ module Flowbite
|
|
|
37
41
|
def hint
|
|
38
42
|
return unless hint?
|
|
39
43
|
|
|
40
|
-
component = Flowbite::Input::Hint.new(
|
|
44
|
+
component = Uchi::Flowbite::Input::Hint.new(
|
|
41
45
|
attribute: @attribute,
|
|
42
46
|
form: @form,
|
|
43
47
|
options: {
|
|
@@ -49,16 +53,16 @@ module Flowbite
|
|
|
49
53
|
end
|
|
50
54
|
|
|
51
55
|
def input_component
|
|
52
|
-
::Flowbite::Input::RadioButton
|
|
56
|
+
Uchi::Flowbite::Input::RadioButton
|
|
53
57
|
end
|
|
54
58
|
|
|
55
59
|
private
|
|
56
60
|
|
|
57
61
|
def hint_classes
|
|
58
62
|
if disabled?
|
|
59
|
-
"text-xs font-normal text-
|
|
63
|
+
"text-xs font-normal text-fg-disabled"
|
|
60
64
|
else
|
|
61
|
-
"text-xs font-normal text-
|
|
65
|
+
"text-xs font-normal text-body"
|
|
62
66
|
end
|
|
63
67
|
end
|
|
64
68
|
|
|
@@ -76,9 +80,9 @@ module Flowbite
|
|
|
76
80
|
|
|
77
81
|
def label_classes
|
|
78
82
|
if disabled?
|
|
79
|
-
"font-medium text-
|
|
83
|
+
"font-medium text-fg-disabled"
|
|
80
84
|
else
|
|
81
|
-
"font-medium text-
|
|
85
|
+
"font-medium text-heading"
|
|
82
86
|
end
|
|
83
87
|
end
|
|
84
88
|
end
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module Flowbite
|
|
3
|
+
module Uchi::Flowbite
|
|
4
4
|
class InputField
|
|
5
5
|
class Select < InputField
|
|
6
|
-
def initialize(attribute:, form:, collection: [], disabled: false, hint: nil, input: {}, label: {}, size: :default)
|
|
6
|
+
def initialize(attribute:, form:, collection: [], disabled: false, hint: nil, include_blank: false, input: {}, label: {}, multiple: false, size: :default)
|
|
7
7
|
super(attribute: attribute, disabled: disabled, form: form, hint: hint, input: input, label: label, size: size)
|
|
8
8
|
@collection = collection
|
|
9
|
+
@include_blank = include_blank
|
|
10
|
+
@multiple = multiple
|
|
9
11
|
end
|
|
10
12
|
|
|
11
13
|
def input
|
|
@@ -15,6 +17,8 @@ module Flowbite
|
|
|
15
17
|
collection: @collection,
|
|
16
18
|
disabled: @disabled,
|
|
17
19
|
form: @form,
|
|
20
|
+
include_blank: @include_blank,
|
|
21
|
+
multiple: @multiple,
|
|
18
22
|
options: input_options,
|
|
19
23
|
size: @size
|
|
20
24
|
)
|
|
@@ -24,7 +28,7 @@ module Flowbite
|
|
|
24
28
|
private
|
|
25
29
|
|
|
26
30
|
def input_component
|
|
27
|
-
::Flowbite::Input::Select
|
|
31
|
+
Uchi::Flowbite::Input::Select
|
|
28
32
|
end
|
|
29
33
|
end
|
|
30
34
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module Flowbite
|
|
3
|
+
module Uchi::Flowbite
|
|
4
4
|
# A form element for a single field, containing label, input field, error
|
|
5
5
|
# messages, helper text and whatever else is needed for a user friendly input
|
|
6
6
|
# experience.
|
|
@@ -71,28 +71,42 @@ module Flowbite
|
|
|
71
71
|
@object.errors[@attribute] || []
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
def initialize(attribute:, form:, disabled: false, hint: nil, input: {}, label: {}, size: :default)
|
|
74
|
+
def initialize(attribute:, form:, class: nil, disabled: false, hint: nil, input: {}, label: {}, options: {}, size: :default)
|
|
75
75
|
@attribute = attribute
|
|
76
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
76
77
|
@disabled = disabled
|
|
77
78
|
@form = form
|
|
78
79
|
@hint = hint
|
|
79
80
|
@input = input
|
|
80
81
|
@label = label
|
|
81
82
|
@object = form.object
|
|
83
|
+
@options = options || {}
|
|
82
84
|
@size = size
|
|
83
85
|
end
|
|
84
86
|
|
|
85
87
|
def input_component
|
|
86
|
-
::Flowbite::Input::Field
|
|
88
|
+
Uchi::Flowbite::Input::Field
|
|
87
89
|
end
|
|
88
90
|
|
|
89
91
|
protected
|
|
90
92
|
|
|
93
|
+
def classes
|
|
94
|
+
if @options[:class]
|
|
95
|
+
Array.wrap(@options[:class])
|
|
96
|
+
else
|
|
97
|
+
[default_container_classes, @class].flatten.compact
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def default_container_classes
|
|
102
|
+
[]
|
|
103
|
+
end
|
|
104
|
+
|
|
91
105
|
# Returns the HTML to use for the hint element if any
|
|
92
106
|
def default_hint
|
|
93
107
|
return unless hint?
|
|
94
108
|
|
|
95
|
-
component = Flowbite::Input::Hint.new(
|
|
109
|
+
component = Uchi::Flowbite::Input::Hint.new(
|
|
96
110
|
attribute: @attribute,
|
|
97
111
|
form: @form,
|
|
98
112
|
options: default_hint_options
|
|
@@ -138,7 +152,7 @@ module Flowbite
|
|
|
138
152
|
end
|
|
139
153
|
|
|
140
154
|
def default_label
|
|
141
|
-
component = Flowbite::Input::Label.new(**default_label_options)
|
|
155
|
+
component = Uchi::Flowbite::Input::Label.new(**default_label_options)
|
|
142
156
|
if default_label_content
|
|
143
157
|
component.with_content(default_label_content)
|
|
144
158
|
else
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uchi::Flowbite
|
|
4
|
+
# The link component can be used to set hyperlinks from one page to another or
|
|
5
|
+
# to an external website when clicking on an inline text item, button, or card
|
|
6
|
+
#
|
|
7
|
+
# Use this component to add default styles to an inline link element.
|
|
8
|
+
class Link < ViewComponent::Base
|
|
9
|
+
attr_reader :href, :options
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
def classes
|
|
13
|
+
["font-medium", "text-fg-brand", "hover:underline"]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Initialize the Link component.
|
|
18
|
+
#
|
|
19
|
+
# @param href What to link to. This can be a String or anything else that
|
|
20
|
+
# `link_to` supports. See `ActionView::Helpers::UrlHelper#link_to` for more
|
|
21
|
+
# details.
|
|
22
|
+
#
|
|
23
|
+
# @param options [Hash] Additional HTML options for the link element
|
|
24
|
+
def initialize(href:, class: nil, **options)
|
|
25
|
+
super()
|
|
26
|
+
@class = Array.wrap(binding.local_variable_get(:class))
|
|
27
|
+
@href = href
|
|
28
|
+
@options = options
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def call
|
|
32
|
+
link_to(content, href, {class: classes}.merge(options))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def classes
|
|
38
|
+
self.class.classes + @class
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<div
|
|
2
|
+
class="<%= container_classes.join(" ") %>"
|
|
3
|
+
role="alert"
|
|
4
|
+
<%= options.map { |k, v| "#{k}=\"#{v}\"" }.join(" ").html_safe %>
|
|
5
|
+
>
|
|
6
|
+
<%= render Uchi::Flowbite::Toast::Icon.new(style: style) %>
|
|
7
|
+
|
|
8
|
+
<div class="ms-3 text-sm font-normal"><%= message %></div>
|
|
9
|
+
|
|
10
|
+
<% if dismissible %>
|
|
11
|
+
<%# Styles from https://flowbite.com/docs/components/toast/#default-toast %>
|
|
12
|
+
<button
|
|
13
|
+
type="button"
|
|
14
|
+
class="
|
|
15
|
+
ms-auto flex items-center justify-center text-body
|
|
16
|
+
hover:text-heading bg-transparent box-border border
|
|
17
|
+
border-transparent hover:bg-neutral-secondary-medium focus:ring-4
|
|
18
|
+
focus:ring-neutral-tertiary font-medium leading-5 rounded text-sm
|
|
19
|
+
h-8 w-8 focus:outline-none
|
|
20
|
+
"
|
|
21
|
+
aria-label="Close"
|
|
22
|
+
>
|
|
23
|
+
<svg
|
|
24
|
+
class="w-3 h-3"
|
|
25
|
+
aria-hidden="true"
|
|
26
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
27
|
+
fill="none"
|
|
28
|
+
viewBox="0 0 14 14"
|
|
29
|
+
>
|
|
30
|
+
<path
|
|
31
|
+
stroke="currentColor"
|
|
32
|
+
stroke-linecap="round"
|
|
33
|
+
stroke-linejoin="round"
|
|
34
|
+
stroke-width="2"
|
|
35
|
+
d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"
|
|
36
|
+
/>
|
|
37
|
+
</svg>
|
|
38
|
+
</button>
|
|
39
|
+
<% end %>
|
|
40
|
+
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module Flowbite
|
|
3
|
+
module Uchi::Flowbite
|
|
4
4
|
# Renders a toast notification element.
|
|
5
5
|
#
|
|
6
6
|
# See https://flowbite.com/docs/components/toast/
|
|
@@ -13,7 +13,7 @@ module Flowbite
|
|
|
13
13
|
class Toast < ViewComponent::Base
|
|
14
14
|
class << self
|
|
15
15
|
def classes
|
|
16
|
-
["flex", "items-center", "w-full", "max-w-xs", "p-4", "text-
|
|
16
|
+
["flex", "items-center", "w-full", "max-w-xs", "p-4", "text-body", "bg-neutral-primary-soft", "rounded-base", "shadow-xs", "border", "border-default"]
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<div class="relative" data-controller="dropdown">
|
|
2
|
+
<%= render(Uchi::Flowbite::Button.new(style: :secondary, :data => {:action => "dropdown#toggle click@window->dropdown#hide"}, id: button_id)) do %>
|
|
3
|
+
<div class="inline-flex items-center">
|
|
4
|
+
<%= repository.translate.actions_button_label %>
|
|
5
|
+
|
|
6
|
+
<svg
|
|
7
|
+
class="w-4 h-4 ms-1.5 -me-0.5"
|
|
8
|
+
aria-hidden="true"
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
width="24"
|
|
11
|
+
height="24"
|
|
12
|
+
fill="none"
|
|
13
|
+
viewBox="0 0 24 24"
|
|
14
|
+
>
|
|
15
|
+
<path
|
|
16
|
+
stroke="currentColor"
|
|
17
|
+
stroke-linecap="round"
|
|
18
|
+
stroke-linejoin="round"
|
|
19
|
+
stroke-width="2"
|
|
20
|
+
d="m19 9-7 7-7-7"
|
|
21
|
+
/>
|
|
22
|
+
</svg>
|
|
23
|
+
</div>
|
|
24
|
+
<% end %>
|
|
25
|
+
|
|
26
|
+
<!-- Dropdown menu -->
|
|
27
|
+
<div
|
|
28
|
+
aria-orientation="vertical"
|
|
29
|
+
aria-hidden="true"
|
|
30
|
+
data-dropdown-target="menu"
|
|
31
|
+
class="
|
|
32
|
+
transition transform origin-top-right absolute z-10 hidden bg-neutral-primary-medium border border-default-medium
|
|
33
|
+
rounded-base shadow-lg w-44 mt-1 -ml-1/2
|
|
34
|
+
"
|
|
35
|
+
id="actions-dropdown-<%= record.id %>"
|
|
36
|
+
role="menu"
|
|
37
|
+
tabindex="-1"
|
|
38
|
+
>
|
|
39
|
+
<ul
|
|
40
|
+
class="p-2 text-sm text-body font-medium"
|
|
41
|
+
aria-labelledby="<%= button_id %>"
|
|
42
|
+
>
|
|
43
|
+
<% actions.each do |action| %>
|
|
44
|
+
<li role="menuitem">
|
|
45
|
+
<%= form_with url: helpers.actions_executions_path, method: :post, class: "block" do %>
|
|
46
|
+
<%= hidden_field_tag :model, repository.model.name %>
|
|
47
|
+
<%= hidden_field_tag :action_name, action.class.name %>
|
|
48
|
+
<%= hidden_field_tag :id, record.id %>
|
|
49
|
+
|
|
50
|
+
<%= button_tag type: "submit",
|
|
51
|
+
class: "block inline-flex items-center w-full p-2 hover:bg-neutral-tertiary-medium hover:text-heading rounded" do %>
|
|
52
|
+
<%= action.name %>
|
|
53
|
+
<% end %>
|
|
54
|
+
<% end %>
|
|
55
|
+
</li>
|
|
56
|
+
<% end %>
|
|
57
|
+
</ul>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Uchi
|
|
4
|
+
module Ui
|
|
5
|
+
module Actions
|
|
6
|
+
# Renders a dropdown menu of actions that can be performed on a record.
|
|
7
|
+
#
|
|
8
|
+
# This component displays available actions for a repository in a dropdown
|
|
9
|
+
# menu. Each action can be clicked to execute it on the specified record(s).
|
|
10
|
+
class Dropdown < ViewComponent::Base
|
|
11
|
+
attr_reader :actions, :record, :repository
|
|
12
|
+
|
|
13
|
+
def initialize(actions:, record:, repository:)
|
|
14
|
+
super()
|
|
15
|
+
@actions = actions
|
|
16
|
+
@record = record
|
|
17
|
+
@repository = repository
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def render?
|
|
21
|
+
actions.any?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def button_id
|
|
27
|
+
"actions-dropdown-button-#{record.id}"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
<%= render(Flowbite::Breadcrumb.new) do |breadcrumb| %>
|
|
1
|
+
<%= render(Uchi::Flowbite::Breadcrumb.new) do |breadcrumb| %>
|
|
2
2
|
<% items.each.with_index do |item, index| %>
|
|
3
3
|
<% breadcrumb.with_item do %>
|
|
4
4
|
<% if index.zero? %>
|
|
5
|
-
<%= render Flowbite::BreadcrumbItem::First.new(href: item[:href]).with_content(item[:label]) %>
|
|
5
|
+
<%= render Uchi::Flowbite::BreadcrumbItem::First.new(href: item[:href]).with_content(item[:label]) %>
|
|
6
6
|
<% elsif index == items.size - 1 %>
|
|
7
|
-
<%= render Flowbite::BreadcrumbItem::Current.new.with_content(item[:label]) %>
|
|
7
|
+
<%= render Uchi::Flowbite::BreadcrumbItem::Current.new.with_content(item[:label]) %>
|
|
8
8
|
<% else %>
|
|
9
|
-
<%= render Flowbite::BreadcrumbItem.new(href: item[:href]).with_content(item[:label]) %>
|
|
9
|
+
<%= render Uchi::Flowbite::BreadcrumbItem.new(href: item[:href]).with_content(item[:label]) %>
|
|
10
10
|
<% end %>
|
|
11
11
|
<% end %>
|
|
12
12
|
<% end %>
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
<div class="flex items-center h-5">
|
|
16
16
|
<%= b.check_box(class: checkbox_classes.join(" "), disabled: disabled?) %>
|
|
17
17
|
</div>
|
|
18
|
+
|
|
18
19
|
<div class="ms-2 text-sm">
|
|
19
20
|
<%= b.label(class: checkbox_label_classes.join(" ")) %>
|
|
20
21
|
</div>
|
|
@@ -27,6 +28,6 @@
|
|
|
27
28
|
<% end %>
|
|
28
29
|
|
|
29
30
|
<% errors.each do |error| %>
|
|
30
|
-
<%= render(Flowbite::Input::ValidationError.new) { error.upcase_first } %>
|
|
31
|
+
<%= render(Uchi::Flowbite::Input::ValidationError.new) { error.upcase_first } %>
|
|
31
32
|
<% end %>
|
|
32
33
|
</div>
|
|
@@ -68,22 +68,22 @@ module Uchi
|
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def label_classes
|
|
71
|
-
base = ["
|
|
71
|
+
base = ["select-none ms-2 text-sm font-medium"]
|
|
72
72
|
if disabled?
|
|
73
|
-
base + ["text-
|
|
73
|
+
base + ["text-fg-disabled"]
|
|
74
74
|
elsif errors?
|
|
75
|
-
base + ["text-
|
|
75
|
+
base + ["text-fg-danger-strong"]
|
|
76
76
|
else
|
|
77
|
-
base + ["text-
|
|
77
|
+
base + ["text-heading"]
|
|
78
78
|
end
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
def hint_classes
|
|
82
82
|
base = ["text-xs", "font-normal", "mt-1"]
|
|
83
83
|
if disabled?
|
|
84
|
-
base + ["text-
|
|
84
|
+
base + ["text-fg-disabled"]
|
|
85
85
|
else
|
|
86
|
-
base + ["text-
|
|
86
|
+
base + ["text-body"]
|
|
87
87
|
end
|
|
88
88
|
end
|
|
89
89
|
|
|
@@ -92,26 +92,21 @@ module Uchi
|
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
def checkbox_classes
|
|
95
|
-
base = ["w-4", "h-4", "
|
|
95
|
+
base = ["w-4", "h-4", "border", "rounded-xs", "focus:ring-2"]
|
|
96
96
|
if disabled?
|
|
97
|
-
base + ["
|
|
98
|
-
"dark:bg-gray-700", "dark:border-gray-600"]
|
|
97
|
+
base + ["border-light", "bg-neutral-secondary-medium", "focus:ring-brand-soft"]
|
|
99
98
|
elsif errors?
|
|
100
|
-
base + ["text-
|
|
101
|
-
"focus:ring-red-500", "dark:focus:ring-red-600",
|
|
102
|
-
"dark:bg-gray-700", "dark:border-red-500"]
|
|
99
|
+
base + ["text-fg-danger", "bg-danger-soft", "border-fg-danger", "focus:ring-fg-danger"]
|
|
103
100
|
else
|
|
104
|
-
base + ["
|
|
105
|
-
"focus:ring-blue-500", "dark:focus:ring-blue-600",
|
|
106
|
-
"dark:bg-gray-700", "dark:border-gray-600"]
|
|
101
|
+
base + ["border-default-medium", "bg-neutral-secondary-medium", "focus:ring-brand-soft"]
|
|
107
102
|
end
|
|
108
103
|
end
|
|
109
104
|
|
|
110
105
|
def checkbox_label_classes
|
|
111
106
|
if disabled?
|
|
112
|
-
["ms-2", "text-sm", "font-medium", "text-
|
|
107
|
+
["select-none", "ms-2", "text-sm", "font-medium", "text-fg-disabled"]
|
|
113
108
|
else
|
|
114
|
-
["ms-2", "text-sm", "font-medium", "text-
|
|
109
|
+
["select-none", "ms-2", "text-sm", "font-medium", "text-heading"]
|
|
115
110
|
end
|
|
116
111
|
end
|
|
117
112
|
|