Files
ubicloud/views/components/form/resource_creation_form.erb
Burak Yucesoy 388808370c Don't add ring around the creation forms for updates
All update forms are in their own subpages now and there is no other components
in those subpages, so additional ring makes the UI look more cluttered than it
should be.
2025-06-19 13:07:10 +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}" }
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>