Files
ubicloud/views/components/form/resource_creation_form.erb
Burak Yucesoy 871ef712b2 Replace dots with dashes in form element classes
Values can contain dots. We use values to generate classes for form elements,
and dots in class names are not valid. This commit replaces dots with dashes
in form element classes. Currently, we don't use dots in any of the values, but
I'll use them in a future PR.
2025-07-01 00:24:58 +03:00

122 lines
5.2 KiB
Plaintext

<%# locals: (action:, form_elements:, option_tree:, option_parents:, method: "POST", pre_selected_values: {}, mode: "create") %>
<% nonce = SecureRandom.base64(32)
content_security_policy.add_script_src [:nonce, nonce] %>
<script nonce="<%==nonce%>">
let option_tree = <%==JSON.generate(option_tree)%>
let option_children = <%==JSON.generate(option_parents.each_with_object(Hash.new { |h, k| h[k] = [] }) { |(child, parents), h| h[parents.last] << child if parents.any? })%>
let option_dirty = <%==JSON.generate(form_elements.map { it[:name] }.each_with_object(Hash.new { |h, k| h[k] = [] }) { |option, h| h[option] = flash.dig("old", option) || pre_selected_values[option] })%>
</script>
<div>
<div class="grid gap-6">
<form action="<%= action %>" method="POST" id="creation-form" class="<%= method %>">
<%== csrf_tag(action, method) %>
<% container_class = (mode == "create") ? "overflow-hidden rounded-lg shadow ring-1 ring-black ring-opacity-5 bg-white" : "" %>
<div class="<%= container_class %>">
<div class="px-4 py-5 sm:p-6">
<div class="space-y-12">
<div>
<div class="mt-2 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<% selected_options = {}
pre_selected_values.each { |k, v| selected_options[k] = v.to_s }
form_elements.each do |element|
container_opening_tag = element[:opening_tag] || "<div class='col-span-full'>"
container_closing_tag = element[:closing_tag] || "</div>"
name, type, label, required, placeholder, content_generator = element.values_at(:name, :type, :label, :required, :placeholder, :content_generator)
has_option = ["radio_small_cards", "select", "checkbox"].include?(type)
options = OptionTreeGenerator.generate_allowed_options(name, option_tree, option_parents).map do |option|
opt_val = if option[name].is_a?(Sequel::Model)
option[name].ubid
elsif type == "select"
option[name][:value]
else
option[name]
end
opt_text = content_generator.call(*option.values)
parents = option.reject { |k, v| k == name }.transform_values { |v| v.is_a?(Sequel::Model) ? v.ubid : v }
parents_selected = parents.all? { |k, v| selected_options[k] == v }
submitted_value = flash.dig("old", name)
selected_in_form_submission = submitted_value == opt_val
selected_in_pre_selection = submitted_value.nil? && selected_options[name] == opt_val
first_of_its_kind = submitted_value.nil? && selected_options[name].nil?
checked = parents_selected && (selected_in_form_submission || selected_in_pre_selection || first_of_its_kind)
selected_options[name] = opt_val if checked
opt_classes = parents.map { |k, v| "form_#{k} form_#{k}_#{v.tr(".", "-")}" }
opt_classes << "hidden" unless parents_selected
opt_classes = opt_classes.join(" ")
opt_attrs = {}
opt_attrs[:disabled] = "disabled" unless parents_selected
opt_attrs[:checked] = checked
[opt_val, opt_text, opt_classes, opt_attrs]
end if has_option
if has_option && selected_options[name].nil?
options.find{ |_, _, _, opt_attrs| opt_attrs[:disabled].nil? }&.tap do |opt_val, _, _, opt_attrs|
opt_attrs[:checked] = true
selected_options[name] = opt_val
end
end
attributes = {required:}
case type
when "radio_small_cards"
locals = {name:, label:, options:, attributes:}
when "select"
locals = {name:, label:, options:, placeholder:, attributes:, description_html: element[:description_html]}
when "checkbox"
locals = {name:, label:, options:, description: element[:description]}
when "text"
locals = {name:, label:, value: element[:value], attributes: attributes.merge!({placeholder:})}
when "number"
locals = {name:, label:, type: "number", attributes: attributes.merge!({placeholder:})}
type = "text"
when "textarea"
locals = {name:, label:, description: element[:description], attributes: attributes.merge!({placeholder:, rows: 3})}
when "hidden"
selected_options[name] = element[:value]
locals = {name:, value: element[:value]}
container_opening_tag, container_closing_tag = "", ""
when "partnership_notice"
description, tos_text = content_generator.call(@flavor)
locals = {description:, tos_text:}
when "section"
locals = {label:, content: element[:content], separator: element[:separator]}
# :nocov:
else
raise "Unknown element type: #{type}"
# :nocov:
end %>
<%== container_opening_tag %>
<%== part("components/form/#{type}", **locals) %>
<%== container_closing_tag %>
<% end %>
</div>
</div>
</div>
</div>
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center justify-end gap-x-6">
<% if mode == "create" %>
<a href="<%= action %>" class="text-sm font-semibold leading-6 text-gray-900">Cancel</a>
<%== part("components/form/submit_button", text: "Create") %>
<% else %>
<%== part("components/form/submit_button", text: "Update") %>
<% end %>
</div>
</div>
</div>
</form>
</div>
</div>