Entity data records for PhoenixKit entities system.
This module manages actual data records that follow entity blueprints. Each record is associated with an entity type and stores its field values in a JSONB column for flexibility.
Schema Fields
entity_uuid: Foreign key to the entity blueprinttitle: Display title/name for the recordslug: URL-friendly identifier (optional)status: Record status ("draft", "published", "archived")data: JSONB map of all field values based on entity definitionmetadata: JSONB map for additional information (tags, categories, etc.)created_by: User UUID who created the recorddate_created: When the record was createddate_updated: When the record was last modified
Core Functions
Data Management
list_all/0- Get all entity data recordslist_by_entity/1- Get all records for a specific entitylist_by_entity_and_status/2- Filter records by entity and statusget!/1- Get a record by ID (raises if not found)get_by_slug/2- Get a record by entity and slugcreate/1- Create a new recordupdate/2- Update an existing recorddelete/1- Delete a recordchange/2- Get changeset for forms
Query Helpers
search_by_title/2- Search records by titlefilter_by_status/1- Get records by statuscount_by_entity/1- Count records for an entitypublished_records/1- Get all published records for an entity
Usage Examples
# Create a brand data record
{:ok, data} = PhoenixKit.Modules.Entities.EntityData.create(%{
entity_uuid: brand_entity.uuid,
title: "Acme Corporation",
slug: "acme-corporation",
status: "published",
created_by_uuid: user.uuid,
data: %{
"name" => "Acme Corporation",
"tagline" => "Quality products since 1950",
"description" => "<p>Leading manufacturer of innovative products</p>",
"industry" => "Manufacturing",
"founded_date" => "1950-03-15",
"featured" => true
},
metadata: %{
"tags" => ["manufacturing", "industrial"],
"contact_email" => "info@acme.com"
}
})
# Get all records for an entity
records = PhoenixKit.Modules.Entities.EntityData.list_by_entity(brand_entity.uuid)
# Search by title
results = PhoenixKit.Modules.Entities.EntityData.search_by_title("Acme", brand_entity.uuid)
Summary
Functions
Bulk deletes multiple records by UUIDs.
Bulk updates positions for multiple records.
Bulk updates the status of multiple records by UUIDs.
Returns an %Ecto.Changeset{} for tracking entity data changes.
Creates a changeset for entity data creation and updates.
Counts the total number of records for an entity.
Creates an entity data record.
Deletes an entity data record.
Alias for delete/1 for consistency with LiveView naming.
Gets records filtered by status across all entities.
Gets a single entity data record by UUID.
Gets a single entity data record by UUID.
Gets all title translations for a record.
Gets translations for all languages in a record.
Gets a single entity data record by entity and slug.
Alias for get!/2 for consistency with LiveView naming.
Gets statistical data about entity data records.
Gets the raw (non-merged) data for a specific language.
Gets the title translation for a specific language.
Gets the data fields for a specific language, merged with primary language defaults.
Returns all entity data records ordered by creation date.
Alias for list_all/1 for consistency with LiveView naming.
Returns all entity data records for a specific entity.
Returns entity data records filtered by entity and status.
Alias for list_by_entity/2 for consistency with LiveView naming.
Alias for filter_by_status/2 for consistency with LiveView naming.
Moves a record to a specific position within its entity, shifting other records.
Gets the next available position for an entity's data records.
Gets all published records for a specific entity.
Removes all data for a specific language from a record.
Reorders all records for an entity based on a list of UUIDs in the desired order.
Resolves translated fields on an entity data record for a given language.
Resolves translations on a list of entity data records.
Searches entity data records by title.
Alias for search_by_title for consistency with LiveView naming.
Checks if a secondary language slug exists for another record within the same entity.
Sets the title translation for a specific language.
Sets the data translation for a specific language on a record.
Updates an entity data record.
Alias for update/2 for consistency with LiveView naming.
Updates the position of a single entity data record.
Types
@type t() :: %PhoenixKit.Modules.Entities.EntityData{ __meta__: term(), created_by_uuid: term(), creator: term(), data: term(), date_created: term(), date_updated: term(), entity: term(), entity_uuid: term(), metadata: term(), position: term(), slug: term(), status: term(), title: term(), uuid: term() }
Functions
Bulk deletes multiple records by UUIDs.
Returns a tuple with the count of deleted records and nil.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.bulk_delete(["uuid1", "uuid2"])
{2, nil}
Bulk updates positions for multiple records.
Accepts a list of {uuid, position} tuples. Each record is updated
individually to trigger events and maintain consistency.
Examples
iex> bulk_update_positions([{"uuid1", 1}, {"uuid2", 2}, {"uuid3", 3}])
:ok
Bulk updates the status of multiple records by UUIDs.
Returns a tuple with the count of updated records and nil.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.bulk_update_status(["uuid1", "uuid2"], "archived")
{2, nil}
Returns an %Ecto.Changeset{} for tracking entity data changes.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.change(record)
%Ecto.Changeset{data: %PhoenixKit.Modules.Entities.EntityData{}}
Creates a changeset for entity data creation and updates.
Validates that entity exists, title is present, and data validates against entity definition. Automatically sets date_created on new records.
Counts the total number of records for an entity.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.count_by_entity(entity_uuid)
42
Creates an entity data record.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.create(%{entity_uuid: entity_uuid, title: "Test"})
{:ok, %PhoenixKit.Modules.Entities.EntityData{}}
iex> PhoenixKit.Modules.Entities.EntityData.create(%{title: ""})
{:error, %Ecto.Changeset{}}Note: created_by is auto-filled with the first admin or user ID if not provided,
but only if at least one user exists in the system. If no users exist, the changeset
will fail with a validation error on created_by.
Deletes an entity data record.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.delete(record)
{:ok, %PhoenixKit.Modules.Entities.EntityData{}}
iex> PhoenixKit.Modules.Entities.EntityData.delete(record)
{:error, %Ecto.Changeset{}}
Alias for delete/1 for consistency with LiveView naming.
Gets records filtered by status across all entities.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.filter_by_status("draft")
[%PhoenixKit.Modules.Entities.EntityData{status: "draft"}, ...]
Gets a single entity data record by UUID.
Returns the record if found, nil otherwise.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.get("550e8400-e29b-41d4-a716-446655440000")
%PhoenixKit.Modules.Entities.EntityData{}
iex> PhoenixKit.Modules.Entities.EntityData.get("invalid")
nil
Gets a single entity data record by UUID.
Raises Ecto.NoResultsError if the record does not exist.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.get!("550e8400-e29b-41d4-a716-446655440000")
%PhoenixKit.Modules.Entities.EntityData{}
iex> PhoenixKit.Modules.Entities.EntityData.get!("nonexistent-uuid")
** (Ecto.NoResultsError)
Gets all title translations for a record.
Returns a map of language codes to title strings.
Examples
iex> get_all_title_translations(record)
%{"en-US" => "My Product", "es-ES" => "Mi Producto", "fr-FR" => "Mon Produit"}
Gets translations for all languages in a record.
Returns a map of language codes to their merged data. For flat records, returns the data under the primary language key.
Examples
iex> get_all_translations(record)
%{
"en-US" => %{"name" => "Acme", "category" => "Tech"},
"es-ES" => %{"name" => "Acme España", "category" => "Tech"}
}
Gets a single entity data record by entity and slug.
Returns the record if found, nil otherwise.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.get_by_slug(entity_uuid, "acme-corporation")
%PhoenixKit.Modules.Entities.EntityData{}
iex> PhoenixKit.Modules.Entities.EntityData.get_by_slug(entity_uuid, "invalid")
nil
Alias for get!/2 for consistency with LiveView naming.
Gets statistical data about entity data records.
Returns statistics about total records, published, draft, and archived counts. Optionally filters by entity_uuid if provided.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.get_data_stats()
%{
total_records: 150,
published_records: 120,
draft_records: 25,
archived_records: 5
}
iex> PhoenixKit.Modules.Entities.EntityData.get_data_stats("018e3c4a-9f6b-7890-abcd-ef1234567890")
%{
total_records: 15,
published_records: 12,
draft_records: 2,
archived_records: 1
}
Gets the raw (non-merged) data for a specific language.
For secondary languages, returns only the override fields (not merged with primary). Useful for seeing which fields have explicit translations.
Examples
iex> get_raw_translation(record, "es-ES")
%{"name" => "Acme España"}
Gets the title translation for a specific language.
Reads from data[lang]["_title"] (unified JSONB storage). Falls back to
the old metadata["translations"] location for unmigrated records, and
finally to the title column.
Examples
iex> get_title_translation(record, "en-US")
"My Product"
iex> get_title_translation(record, "es-ES")
"Mi Producto"
Gets the data fields for a specific language, merged with primary language defaults.
For multilang records, returns Map.merge(primary_data, language_overrides).
For flat (non-multilang) records, returns the data as-is.
Examples
iex> get_translation(record, "es-ES")
%{"name" => "Acme España", "category" => "Tech"}
iex> get_translation(flat_record, "en-US")
%{"name" => "Acme", "category" => "Tech"}
Returns all entity data records ordered by creation date.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.list_all()
[%PhoenixKit.Modules.Entities.EntityData{}, ...]
Alias for list_all/1 for consistency with LiveView naming.
Returns all entity data records for a specific entity.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.list_by_entity(entity_uuid)
[%PhoenixKit.Modules.Entities.EntityData{}, ...]
Returns entity data records filtered by entity and status.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.list_by_entity_and_status(entity_uuid, "published")
[%PhoenixKit.Modules.Entities.EntityData{status: "published"}, ...]
Alias for list_by_entity/2 for consistency with LiveView naming.
Alias for filter_by_status/2 for consistency with LiveView naming.
Moves a record to a specific position within its entity, shifting other records.
Records between the old and new positions are shifted up or down by 1 to make room. This is the operation that a drag-and-drop UI would call.
Examples
iex> move_to_position(record, 3)
:ok
Gets the next available position for an entity's data records.
Examples
iex> next_position(entity_uuid)
6
Gets all published records for a specific entity.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.published_records(entity_uuid)
[%PhoenixKit.Modules.Entities.EntityData{status: "published"}, ...]
Removes all data for a specific language from a record.
Cannot remove the primary language. Returns {:error, :cannot_remove_primary}
if the primary language is targeted.
Examples
iex> remove_translation(record, "es-ES")
{:ok, %EntityData{}}
iex> remove_translation(record, "en-US")
{:error, :cannot_remove_primary}
Reorders all records for an entity based on a list of UUIDs in the desired order.
This is the full reorder operation — takes a list of UUIDs representing the new order and assigns positions 1, 2, 3, ... accordingly.
Examples
iex> reorder(entity_uuid, ["uuid3", "uuid1", "uuid2"])
:ok
Resolves translated fields on an entity data record for a given language.
Resolves the title from _title in the language's data, and replaces
the data field with the merged language data (primary as base + overrides).
For the primary language or flat (non-multilang) data, the struct is returned with the primary language data resolved. When no translation exists for a field, the primary language value is used as fallback.
Examples
iex> resolve_language(record, "es-ES")
%EntityData{title: "Mi Producto", data: %{"name" => "Acme España", ...}}
iex> resolve_language(record, "en-US") # primary language
%EntityData{title: "My Product", data: %{"name" => "Acme", ...}}
Resolves translations on a list of entity data records.
Examples
iex> resolve_languages(records, "es-ES")
[%EntityData{title: "Mi Producto"}, ...]
Searches entity data records by title.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.search_by_title("Acme")
[%PhoenixKit.Modules.Entities.EntityData{}, ...]
iex> PhoenixKit.Modules.Entities.EntityData.search_by_title("Acme", entity_uuid)
[%PhoenixKit.Modules.Entities.EntityData{}, ...]
iex> PhoenixKit.Modules.Entities.EntityData.search_by_title("Acme", entity_uuid, lang: "es")
[%PhoenixKit.Modules.Entities.EntityData{}, ...]
Alias for search_by_title for consistency with LiveView naming.
Checks if a secondary language slug exists for another record within the same entity.
Queries the JSONB data column for data->lang_code->>'_slug' matches.
Used for uniqueness checks on translated slugs.
Sets the title translation for a specific language.
Stores _title in the JSONB data column using put_language_data.
For the primary language, also updates the title DB column.
Examples
iex> set_title_translation(record, "es-ES", "Mi Producto")
{:ok, %EntityData{}}
iex> set_title_translation(record, "en-US", "My Product")
{:ok, %EntityData{}}
Sets the data translation for a specific language on a record.
For the primary language, stores all fields. For secondary languages, only stores fields that differ from primary (overrides). Persists to the database.
Examples
iex> set_translation(record, "es-ES", %{"name" => "Acme España"})
{:ok, %EntityData{}}
iex> set_translation(record, "en-US", %{"name" => "Acme Corp", "category" => "Tech"})
{:ok, %EntityData{}}
Updates an entity data record.
Examples
iex> PhoenixKit.Modules.Entities.EntityData.update(record, %{title: "Updated"})
{:ok, %PhoenixKit.Modules.Entities.EntityData{}}
iex> PhoenixKit.Modules.Entities.EntityData.update(record, %{title: ""})
{:error, %Ecto.Changeset{}}
Alias for update/2 for consistency with LiveView naming.
Updates the position of a single entity data record.
Examples
iex> update_position(record, 3)
{:ok, %EntityData{position: 3}}