ubicloud/views/components/form/resource_creation_form.erb
Jeremy Evans 996931d35b Show link to SSH public key management page on VM create page
If the user has not already registered an SSH public key, and they
have permission to do so, show a link to the page. This makes it
more likely users will be aware of this feature.

If the project has a registered SSH public key, we don't need to
explain the benefit of an SSH public key, so hide the description
in that case.
2025-10-04 01:36:33 +09:00

113 lines
5 KiB
Text

<%# 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] = typecast_body_params.str(option) || pre_selected_values[option] })%>
</script>
<div>
<div class="grid gap-6">
<% form(action:, method:, id: "creation-form", class: method) do %>
<% 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 = typecast_body_params.str(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? unless type == "checkbox" && !request.get?
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
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], escape_description: element.fetch(:escape_description, true), attributes: attributes.merge!({placeholder:, rows: 3})}
when "hidden"
selected_options[name] = element[:value]
locals = {name => 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>
<% end %>
</div>
</div>