Packages
phoenix_kit
1.7.44
1.7.207
1.7.206
1.7.205
1.7.204
1.7.203
1.7.202
1.7.201
1.7.200
1.7.199
1.7.198
1.7.197
1.7.196
1.7.194
1.7.193
1.7.192
1.7.191
1.7.190
1.7.189
1.7.187
1.7.186
1.7.185
1.7.184
1.7.183
1.7.182
1.7.181
1.7.180
1.7.179
1.7.178
1.7.177
1.7.176
1.7.175
1.7.174
1.7.173
1.7.172
1.7.171
1.7.170
1.7.169
1.7.168
1.7.167
1.7.166
1.7.165
1.7.164
1.7.162
1.7.161
1.7.160
1.7.159
1.7.157
1.7.156
1.7.155
1.7.154
1.7.153
1.7.152
1.7.151
1.7.150
1.7.149
1.7.146
1.7.145
1.7.144
1.7.143
1.7.138
1.7.133
1.7.132
1.7.131
1.7.130
1.7.128
1.7.126
1.7.125
1.7.121
1.7.120
1.7.119
1.7.118
1.7.117
1.7.116
1.7.115
1.7.114
1.7.113
1.7.112
1.7.111
1.7.110
1.7.109
1.7.108
1.7.107
1.7.106
1.7.105
1.7.104
1.7.103
1.7.102
1.7.101
1.7.100
1.7.99
1.7.98
1.7.97
1.7.96
1.7.95
1.7.94
1.7.93
1.7.92
1.7.91
1.7.90
1.7.89
1.7.88
1.7.87
1.7.86
1.7.85
1.7.84
1.7.83
1.7.82
1.7.81
1.7.80
1.7.79
1.7.78
1.7.77
1.7.76
1.7.75
1.7.74
1.7.71
1.7.70
1.7.69
1.7.66
1.7.65
1.7.64
1.7.63
1.7.62
1.7.61
1.7.59
1.7.58
1.7.57
1.7.56
1.7.55
1.7.54
1.7.53
1.7.52
1.7.51
1.7.49
1.7.44
1.7.43
1.7.42
1.7.41
1.7.39
1.7.38
1.7.37
1.7.36
1.7.34
1.7.33
1.7.31
1.7.30
1.7.29
1.7.28
1.7.27
1.7.26
1.7.25
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.20
1.6.19
1.6.18
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.10
1.2.9
1.2.8
1.2.7
1.2.5
1.2.4
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more
Current section
Files
Jump to
Current section
Files
lib/modules/shared/components/entity_form.ex
defmodule PhoenixKit.Modules.Shared.Components.EntityForm do
@moduledoc """
Embeddable entity form component for publishing pages.
Renders a public submission form based on entity configuration.
## Usage in .phk files
<EntityForm entity_slug="contact" />
## Attributes
- `entity_slug` (required) - The slug/name of the entity to render form for
"""
use Phoenix.Component
use Gettext, backend: PhoenixKitWeb.Gettext
alias PhoenixKit.Modules.Entities
alias PhoenixKit.Modules.Entities.EntityData
alias PhoenixKit.Modules.Entities.FormBuilder
alias PhoenixKit.Utils.Date, as: UtilsDate
attr :content, :string, default: nil
attr :attributes, :map, default: %{}
attr :variant, :string, default: "default"
def render(assigns) do
entity_slug = Map.get(assigns.attributes, "entity_slug", "")
# Load entity and check if public form is enabled
entity = if entity_slug != "", do: Entities.get_entity_by_name(entity_slug), else: nil
{form_enabled, form_fields, form_title, form_description, form_submit_text, honeypot_enabled} =
if entity do
settings = entity.settings || %{}
enabled = Map.get(settings, "public_form_enabled", false)
fields = Map.get(settings, "public_form_fields", [])
# Form is only truly enabled if it's enabled AND has at least one field selected
actually_enabled = enabled && not Enum.empty?(fields)
title = Map.get(settings, "public_form_title", "")
description = Map.get(settings, "public_form_description", "")
submit_text = Map.get(settings, "public_form_submit_text", gettext("Submit"))
honeypot = Map.get(settings, "public_form_honeypot", false)
{actually_enabled, fields, title, description, submit_text, honeypot}
else
{false, [], "", "", gettext("Submit"), false}
end
# Create a form entity with only the public form fields
form_entity =
if entity && form_enabled do
fields_definition = entity.fields_definition || []
public_fields =
Enum.filter(fields_definition, fn field ->
field["key"] in form_fields
end)
%{entity | fields_definition: public_fields}
else
nil
end
assigns =
assigns
|> assign(:entity_slug, entity_slug)
|> assign(:entity, entity)
|> assign(:form_entity, form_entity)
|> assign(:form_enabled, form_enabled)
|> assign(:form_title, form_title)
|> assign(:form_description, form_description)
|> assign(:form_submit_text, form_submit_text)
|> assign(:honeypot_enabled, honeypot_enabled)
|> assign(:form_timestamp, UtilsDate.utc_now() |> DateTime.to_iso8601())
~H"""
<div class="entity-form-wrapper">
<%= cond do %>
<% @entity_slug == "" -> %>
<div class="card bg-base-100 shadow-xl">
<div class="card-body text-center py-8">
<div class="text-4xl mb-3">⚠️</div>
<p class="text-base-content/70">{gettext("Form configuration error.")}</p>
</div>
</div>
<% is_nil(@entity) -> %>
<div class="card bg-base-100 shadow-xl">
<div class="card-body text-center py-8">
<div class="text-4xl mb-3">⚠️</div>
<p class="text-base-content/70">{gettext("Form configuration error.")}</p>
</div>
</div>
<% !@form_enabled -> %>
<div class="card bg-base-100 shadow-xl">
<div class="card-body text-center py-8">
<div class="text-4xl mb-3">📝</div>
<p class="text-base-content/70">{gettext("This form is currently unavailable.")}</p>
</div>
</div>
<% true -> %>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<%= if @form_title != "" do %>
<h2 class="card-title text-2xl mb-2">{@form_title}</h2>
<% end %>
<%= if @form_description != "" do %>
<p class="text-base-content/70 mb-4">{@form_description}</p>
<% end %>
<form
action={PhoenixKit.Utils.Routes.path("/entities/#{@entity_slug}/submit")}
method="post"
>
<input type="hidden" name="_csrf_token" value={Phoenix.Controller.get_csrf_token()} />
<%!-- Form loaded timestamp (always included for metadata) --%>
<input type="hidden" name="_form_loaded_at" value={@form_timestamp} />
<%!-- Honeypot field (hidden from humans, bots will fill it) --%>
<%= if @honeypot_enabled do %>
<div style="position: absolute; left: -9999px;" aria-hidden="true">
<label for="_hp_website">Leave this field empty</label>
<input
type="text"
name="_hp_website"
id="_hp_website"
tabindex="-1"
autocomplete="off"
/>
</div>
<% end %>
{FormBuilder.build_fields(@form_entity, build_empty_changeset(@entity),
wrapper_class: "mb-4"
)}
<div class="form-control mt-6">
<button type="submit" class="btn btn-primary">
{@form_submit_text}
</button>
</div>
</form>
</div>
</div>
<% end %>
</div>
"""
end
defp build_empty_changeset(entity) do
# Create an empty EntityData changeset for the form
%EntityData{entity_id: entity.id, entity_uuid: entity.uuid, data: %{}}
|> EntityData.change()
end
end