ruflet_rails 0.0.7 → 0.0.8

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.
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ruflet
4
+ module Rails
5
+ module FormHelpers
6
+ def ruflet_form_bindings(record, form_fields)
7
+ form_fields.to_h do |field|
8
+ [field[:name], ruflet_field_binding(field, record)]
9
+ end
10
+ end
11
+
12
+ def ruflet_form_controls(bindings)
13
+ bindings.values.map { |binding| binding[:control] }
14
+ end
15
+
16
+ def ruflet_form_attributes(bindings, form_fields)
17
+ bindings.to_h do |name, binding|
18
+ field = form_fields.find { |candidate| candidate[:name] == name }
19
+ control = binding[:input] || binding[:control] || binding
20
+ [name, ruflet_control_value(control, field[:type])]
21
+ end
22
+ end
23
+
24
+ def ruflet_show_errors(record)
25
+ ruflet_show_snackbar(ruflet_error_message(record))
26
+ end
27
+
28
+ def ruflet_show_snackbar(message)
29
+ page.snackbar = snackbar(text(message), open: true)
30
+ end
31
+
32
+ private
33
+
34
+ def ruflet_field_binding(field, record)
35
+ type = field[:type].to_s
36
+ return ruflet_picker_field_binding(field, record) if %w[date datetime timestamp time].include?(type)
37
+
38
+ control = ruflet_field_control(field, record)
39
+ { control: control, input: control }
40
+ end
41
+
42
+ def ruflet_field_control(field, record)
43
+ name = field[:name]
44
+ type = field[:type].to_s
45
+ value = record.public_send(name)
46
+ label = name.humanize
47
+
48
+ case type
49
+ when "association", "references", "belongs_to"
50
+ dropdown(
51
+ ruflet_association_options(field),
52
+ value: value.to_s,
53
+ label: label
54
+ )
55
+ when "boolean"
56
+ checkbox(label: label, value: !!value)
57
+ when "integer", "float", "decimal"
58
+ text_field(value: value.to_s, label: label, keyboard_type: "number")
59
+ when "text"
60
+ text_field(value: value.to_s, label: label, multiline: true, min_lines: 3)
61
+ else
62
+ text_field(value: value.to_s, label: label)
63
+ end
64
+ end
65
+
66
+ def ruflet_picker_field_binding(field, record)
67
+ name = field[:name]
68
+ type = field[:type].to_s
69
+ value = record.public_send(name)
70
+ label = name.humanize
71
+ picker = ruflet_picker_control(type, value, label)
72
+ display = text(ruflet_picker_display_text(label, picker.props["value"]))
73
+
74
+ picker.on(:change) do |_event|
75
+ page.update(picker, open: false)
76
+ page.close_dialog(picker)
77
+ page.update(display, value: ruflet_picker_display_text(label, picker.props["value"]))
78
+ end
79
+ picker.on(:dismiss) do |_event|
80
+ page.update(picker, open: false)
81
+ page.close_dialog(picker)
82
+ end
83
+
84
+ {
85
+ control: column(
86
+ spacing: 6,
87
+ children: [
88
+ display,
89
+ outlined_button(
90
+ content: text("Choose #{label}"),
91
+ on_click: ->(_e) { page.show_dialog(picker) }
92
+ )
93
+ ]
94
+ ),
95
+ input: picker
96
+ }
97
+ end
98
+
99
+ def ruflet_picker_control(type, value, label)
100
+ case type
101
+ when "time"
102
+ time_picker(value: value.respond_to?(:strftime) ? value.strftime("%H:%M") : value.to_s, help_text: label, open: false)
103
+ when "datetime", "timestamp"
104
+ date_picker(value: ruflet_date_value(value), help_text: label, open: false)
105
+ else
106
+ date_picker(value: ruflet_date_value(value), help_text: label, open: false)
107
+ end
108
+ end
109
+
110
+ def ruflet_control_value(control, type)
111
+ value = control.props["value"]
112
+ return nil if value.to_s.empty?
113
+ return value if type.to_s == "boolean"
114
+ return value if %w[association references belongs_to].include?(type.to_s)
115
+ return value.to_s.split("T", 2).first if type.to_s == "date"
116
+ return value.to_s if %w[datetime timestamp time].include?(type.to_s)
117
+
118
+ value.to_s
119
+ end
120
+
121
+ def ruflet_association_options(field)
122
+ model = ruflet_association_model(field)
123
+ return [] unless model.respond_to?(:all)
124
+
125
+ model.all.map do |record|
126
+ dropdown_option(record.id.to_s, text: ruflet_association_label(record))
127
+ end
128
+ end
129
+
130
+ def ruflet_association_model(field)
131
+ class_name = field[:class_name] || field[:name].to_s.sub(/_id\z/, "").camelize
132
+ class_name.safe_constantize if class_name.respond_to?(:safe_constantize)
133
+ end
134
+
135
+ def ruflet_association_label(record)
136
+ return record.name.to_s if record.respond_to?(:name)
137
+ return record.title.to_s if record.respond_to?(:title)
138
+
139
+ record.to_s
140
+ end
141
+
142
+ def ruflet_date_value(value)
143
+ return nil if value.nil?
144
+ return value.iso8601 if value.respond_to?(:iso8601)
145
+ return value.to_date.iso8601 if value.respond_to?(:to_date)
146
+
147
+ value.to_s
148
+ end
149
+
150
+ def ruflet_picker_display_text(label, value)
151
+ visible = value.to_s.empty? ? "Not selected" : value.to_s.split("T", 2).first
152
+ "#{label}: #{visible}"
153
+ end
154
+
155
+ def ruflet_error_message(record)
156
+ messages = record.errors.full_messages
157
+ messages.respond_to?(:to_sentence) ? messages.to_sentence : messages.join(", ")
158
+ end
159
+ end
160
+ end
161
+ end