refactor: remove code duplication using helper modules
This commit is contained in:
parent
4a1042ab1a
commit
30c43271ea
4 changed files with 45 additions and 220 deletions
|
|
@ -18,6 +18,8 @@ defmodule MvWeb.Components.FieldVisibilityDropdownComponent do
|
||||||
|
|
||||||
use MvWeb, :live_component
|
use MvWeb, :live_component
|
||||||
|
|
||||||
|
alias MvWeb.Translations.MemberFields
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# UPDATE
|
# UPDATE
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
@ -66,7 +68,7 @@ defmodule MvWeb.Components.FieldVisibilityDropdownComponent do
|
||||||
<.dropdown_menu
|
<.dropdown_menu
|
||||||
id="field-visibility-menu"
|
id="field-visibility-menu"
|
||||||
icon="hero-adjustments-horizontal"
|
icon="hero-adjustments-horizontal"
|
||||||
button_label={gettext("Columns")}
|
button_label={gettext("Show/Hide Columns")}
|
||||||
items={@all_items}
|
items={@all_items}
|
||||||
checkboxes={true}
|
checkboxes={true}
|
||||||
selected={@selected_fields}
|
selected={@selected_fields}
|
||||||
|
|
@ -153,12 +155,12 @@ defmodule MvWeb.Components.FieldVisibilityDropdownComponent do
|
||||||
defp field_to_string(field) when is_binary(field), do: field
|
defp field_to_string(field) when is_binary(field), do: field
|
||||||
|
|
||||||
defp format_field_label(field) when is_atom(field) do
|
defp format_field_label(field) when is_atom(field) do
|
||||||
MvWeb.Translations.MemberFields.label(field)
|
MemberFields.label(field)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp format_field_label(field) when is_binary(field) do
|
defp format_field_label(field) when is_binary(field) do
|
||||||
case safe_to_existing_atom(field) do
|
case safe_to_existing_atom(field) do
|
||||||
{:ok, atom} -> MvWeb.Translations.MemberFields.label(atom)
|
{:ok, atom} -> MemberFields.label(atom)
|
||||||
:error -> fallback_label(field)
|
:error -> fallback_label(field)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,22 +3,28 @@ defmodule MvWeb.MemberFieldLive.FormComponent do
|
||||||
LiveComponent form for editing member field properties (embedded in settings).
|
LiveComponent form for editing member field properties (embedded in settings).
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
- Edit member field properties (name, value type, description, immutable, required, show in overview)
|
- Edit member field visibility (show_in_overview)
|
||||||
- Display member field information from Member Resource
|
- Display member field information from Member Resource (read-only)
|
||||||
- Restrict editing for email field (only show_in_overview can be changed)
|
- Restrict editing for email field (only show_in_overview can be changed)
|
||||||
- Real-time validation
|
- Real-time validation
|
||||||
- Updates Settings.member_field_visibility
|
- Updates Settings.member_field_visibility atomically
|
||||||
|
|
||||||
## Props
|
## Props
|
||||||
- `member_field` - The member field atom to edit (e.g., :first_name, :email)
|
- `member_field` - The member field atom to edit (e.g., :first_name, :email)
|
||||||
- `settings` - The current Settings resource
|
- `settings` - The current Settings resource
|
||||||
- `on_save` - Callback function to call when form is saved
|
- `on_save` - Callback function to call when form is saved
|
||||||
- `on_cancel` - Callback function to call when form is cancelled
|
- `on_cancel` - Callback function to call when form is cancelled
|
||||||
|
|
||||||
|
## Note
|
||||||
|
Member fields are technical fields that cannot be changed (name, value_type, description, required).
|
||||||
|
Only the visibility (show_in_overview) can be modified.
|
||||||
"""
|
"""
|
||||||
use MvWeb, :live_component
|
use MvWeb, :live_component
|
||||||
|
|
||||||
|
alias Mv.Helpers.TypeParsers
|
||||||
alias Mv.Membership
|
alias Mv.Membership
|
||||||
alias MvWeb.Translations.FieldTypes
|
alias Mv.Membership.Helpers.VisibilityConfig
|
||||||
|
alias MvWeb.Helpers.FieldTypeFormatter
|
||||||
alias MvWeb.Translations.MemberFields
|
alias MvWeb.Translations.MemberFields
|
||||||
|
|
||||||
@required_fields [:first_name, :last_name, :email]
|
@required_fields [:first_name, :last_name, :email]
|
||||||
|
|
@ -39,7 +45,7 @@ defmodule MvWeb.MemberFieldLive.FormComponent do
|
||||||
type="button"
|
type="button"
|
||||||
phx-click="cancel"
|
phx-click="cancel"
|
||||||
phx-target={@myself}
|
phx-target={@myself}
|
||||||
aria-label={gettext("Back to member field overview")}
|
aria-label={gettext("Back to Settings")}
|
||||||
>
|
>
|
||||||
<.icon name="hero-arrow-left" class="w-4 h-4" />
|
<.icon name="hero-arrow-left" class="w-4 h-4" />
|
||||||
</.button>
|
</.button>
|
||||||
|
|
@ -102,7 +108,7 @@ defmodule MvWeb.MemberFieldLive.FormComponent do
|
||||||
type="text"
|
type="text"
|
||||||
name={@form[:value_type].name}
|
name={@form[:value_type].name}
|
||||||
id={@form[:value_type].id}
|
id={@form[:value_type].id}
|
||||||
value={format_value_type(@field_attributes.value_type)}
|
value={FieldTypeFormatter.format(@field_attributes.value_type)}
|
||||||
disabled
|
disabled
|
||||||
readonly
|
readonly
|
||||||
class="w-full input"
|
class="w-full input"
|
||||||
|
|
@ -148,47 +154,6 @@ defmodule MvWeb.MemberFieldLive.FormComponent do
|
||||||
readonly={@is_email_field?}
|
readonly={@is_email_field?}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
|
||||||
:if={@is_email_field?}
|
|
||||||
class="tooltip tooltip-right"
|
|
||||||
data-tip={gettext("This is a technical field and cannot be changed")}
|
|
||||||
aria-label={gettext("This is a technical field and cannot be changed")}
|
|
||||||
>
|
|
||||||
<fieldset class="mb-2 fieldset">
|
|
||||||
<label>
|
|
||||||
<input type="hidden" name={@form[:immutable].name} value="false" disabled />
|
|
||||||
<span class="label flex items-center gap-2">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
name={@form[:immutable].name}
|
|
||||||
id={@form[:immutable].id}
|
|
||||||
value="true"
|
|
||||||
checked={@form[:immutable].value}
|
|
||||||
disabled
|
|
||||||
readonly
|
|
||||||
class="checkbox checkbox-sm"
|
|
||||||
/>
|
|
||||||
<span class="flex items-center gap-2">
|
|
||||||
{gettext("Immutable")}
|
|
||||||
<.icon
|
|
||||||
name="hero-information-circle"
|
|
||||||
class="w-4 h-4 text-base-content/60 cursor-help"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
<.input
|
|
||||||
:if={not @is_email_field?}
|
|
||||||
field={@form[:immutable]}
|
|
||||||
type="checkbox"
|
|
||||||
label={gettext("Immutable")}
|
|
||||||
disabled={@is_email_field?}
|
|
||||||
readonly={@is_email_field?}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
:if={@is_email_field?}
|
:if={@is_email_field?}
|
||||||
class="tooltip tooltip-right"
|
class="tooltip tooltip-right"
|
||||||
|
|
@ -266,11 +231,13 @@ defmodule MvWeb.MemberFieldLive.FormComponent do
|
||||||
|
|
||||||
updated_params =
|
updated_params =
|
||||||
member_field_params
|
member_field_params
|
||||||
|> Map.put("show_in_overview", parse_boolean(member_field_params["show_in_overview"]))
|
|> Map.put(
|
||||||
|
"show_in_overview",
|
||||||
|
TypeParsers.parse_boolean(member_field_params["show_in_overview"])
|
||||||
|
)
|
||||||
|> Map.put("name", form.source["name"])
|
|> Map.put("name", form.source["name"])
|
||||||
|> Map.put("value_type", form.source["value_type"])
|
|> Map.put("value_type", form.source["value_type"])
|
||||||
|> Map.put("description", form.source["description"])
|
|> Map.put("description", form.source["description"])
|
||||||
|> Map.put("immutable", form.source["immutable"])
|
|
||||||
|> Map.put("required", form.source["required"])
|
|> Map.put("required", form.source["required"])
|
||||||
|
|
||||||
updated_form =
|
updated_form =
|
||||||
|
|
@ -284,29 +251,15 @@ defmodule MvWeb.MemberFieldLive.FormComponent do
|
||||||
@impl true
|
@impl true
|
||||||
def handle_event("save", %{"member_field" => member_field_params}, socket) do
|
def handle_event("save", %{"member_field" => member_field_params}, socket) do
|
||||||
# Only show_in_overview can be changed for member fields
|
# Only show_in_overview can be changed for member fields
|
||||||
show_in_overview = parse_boolean(member_field_params["show_in_overview"])
|
show_in_overview = TypeParsers.parse_boolean(member_field_params["show_in_overview"])
|
||||||
|
|
||||||
# Get current visibility config and update only the current field
|
|
||||||
current_visibility = socket.assigns.settings.member_field_visibility || %{}
|
|
||||||
field_string = Atom.to_string(socket.assigns.member_field)
|
field_string = Atom.to_string(socket.assigns.member_field)
|
||||||
|
|
||||||
# Normalize keys to strings
|
# Use atomic action to update only this single field
|
||||||
normalized_visibility =
|
# This prevents lost updates in concurrent scenarios
|
||||||
Enum.reduce(current_visibility, %{}, fn
|
case Membership.update_single_member_field_visibility(
|
||||||
{key, value}, acc when is_atom(key) ->
|
|
||||||
Map.put(acc, Atom.to_string(key), value)
|
|
||||||
|
|
||||||
{key, value}, acc when is_binary(key) ->
|
|
||||||
Map.put(acc, key, value)
|
|
||||||
end)
|
|
||||||
|
|
||||||
# Update the specific field
|
|
||||||
updated_visibility = Map.put(normalized_visibility, field_string, show_in_overview)
|
|
||||||
|
|
||||||
# Update settings with new visibility
|
|
||||||
case Membership.update_member_field_visibility(
|
|
||||||
socket.assigns.settings,
|
socket.assigns.settings,
|
||||||
updated_visibility
|
field: field_string,
|
||||||
|
show_in_overview: show_in_overview
|
||||||
) do
|
) do
|
||||||
{:ok, _updated_settings} ->
|
{:ok, _updated_settings} ->
|
||||||
socket.assigns.on_save.(socket.assigns.member_field, "update")
|
socket.assigns.on_save.(socket.assigns.member_field, "update")
|
||||||
|
|
@ -335,15 +288,15 @@ defmodule MvWeb.MemberFieldLive.FormComponent do
|
||||||
defp assign_form(%{assigns: %{member_field: member_field, settings: settings}} = socket) do
|
defp assign_form(%{assigns: %{member_field: member_field, settings: settings}} = socket) do
|
||||||
field_attributes = get_field_attributes(member_field)
|
field_attributes = get_field_attributes(member_field)
|
||||||
visibility_config = settings.member_field_visibility || %{}
|
visibility_config = settings.member_field_visibility || %{}
|
||||||
normalized_config = normalize_visibility_config(visibility_config)
|
normalized_config = VisibilityConfig.normalize(visibility_config)
|
||||||
show_in_overview = Map.get(normalized_config, member_field, true)
|
show_in_overview = Map.get(normalized_config, member_field, true)
|
||||||
|
|
||||||
# Create a manual form structure with string keys
|
# Create a manual form structure with string keys
|
||||||
|
# Note: immutable is not included as it's not editable for member fields
|
||||||
form_data = %{
|
form_data = %{
|
||||||
"name" => MemberFields.label(member_field),
|
"name" => MemberFields.label(member_field),
|
||||||
"value_type" => format_value_type(field_attributes.value_type),
|
"value_type" => FieldTypeFormatter.format(field_attributes.value_type),
|
||||||
"description" => field_attributes.description || "",
|
"description" => field_attributes.description || "",
|
||||||
"immutable" => field_attributes.immutable,
|
|
||||||
"required" => field_attributes.required,
|
"required" => field_attributes.required,
|
||||||
"show_in_overview" => show_in_overview
|
"show_in_overview" => show_in_overview
|
||||||
}
|
}
|
||||||
|
|
@ -355,13 +308,14 @@ defmodule MvWeb.MemberFieldLive.FormComponent do
|
||||||
|
|
||||||
defp get_field_attributes(field) when is_atom(field) do
|
defp get_field_attributes(field) when is_atom(field) do
|
||||||
# Get attribute info from Member Resource
|
# Get attribute info from Member Resource
|
||||||
case Ash.Resource.Info.attribute(Mv.Membership.Member, field) do
|
alias Ash.Resource.Info
|
||||||
|
|
||||||
|
case Info.attribute(Mv.Membership.Member, field) do
|
||||||
nil ->
|
nil ->
|
||||||
# Fallback for fields not in resource (shouldn't happen with Constants)
|
# Fallback for fields not in resource (shouldn't happen with Constants)
|
||||||
%{
|
%{
|
||||||
value_type: :string,
|
value_type: :string,
|
||||||
description: nil,
|
description: nil,
|
||||||
immutable: field == :email,
|
|
||||||
required: field in @required_fields
|
required: field in @required_fields
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -369,72 +323,11 @@ defmodule MvWeb.MemberFieldLive.FormComponent do
|
||||||
%{
|
%{
|
||||||
value_type: attribute.type,
|
value_type: attribute.type,
|
||||||
description: nil,
|
description: nil,
|
||||||
immutable: field == :email,
|
|
||||||
required: not attribute.allow_nil?
|
required: not attribute.allow_nil?
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp format_value_type(type) when is_atom(type) do
|
|
||||||
type_string = to_string(type)
|
|
||||||
|
|
||||||
# Check if it's an Ash type module (e.g., Ash.Type.String or Elixir.Ash.Type.String)
|
|
||||||
if String.contains?(type_string, "Ash.Type.") do
|
|
||||||
# Extract the base type name from Ash type modules
|
|
||||||
# e.g., "Elixir.Ash.Type.String" -> "String" -> :string
|
|
||||||
type_name =
|
|
||||||
type_string
|
|
||||||
|> String.split(".")
|
|
||||||
|> List.last()
|
|
||||||
|> String.downcase()
|
|
||||||
|
|
||||||
try do
|
|
||||||
type_atom = String.to_existing_atom(type_name)
|
|
||||||
FieldTypes.label(type_atom)
|
|
||||||
rescue
|
|
||||||
ArgumentError ->
|
|
||||||
# Fallback if atom doesn't exist
|
|
||||||
FieldTypes.label(:string)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
# It's already an atom like :string, :boolean, :date
|
|
||||||
FieldTypes.label(type)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp format_value_type(type) do
|
|
||||||
# Fallback for unknown types
|
|
||||||
to_string(type)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp normalize_visibility_config(config) when is_map(config) do
|
|
||||||
Enum.reduce(config, %{}, fn
|
|
||||||
{key, value}, acc when is_atom(key) ->
|
|
||||||
Map.put(acc, key, value)
|
|
||||||
|
|
||||||
{key, value}, acc when is_binary(key) ->
|
|
||||||
try do
|
|
||||||
atom_key = String.to_existing_atom(key)
|
|
||||||
Map.put(acc, atom_key, value)
|
|
||||||
rescue
|
|
||||||
ArgumentError ->
|
|
||||||
acc
|
|
||||||
end
|
|
||||||
|
|
||||||
_, acc ->
|
|
||||||
acc
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp normalize_visibility_config(_), do: %{}
|
|
||||||
|
|
||||||
defp parse_boolean(value) when is_boolean(value), do: value
|
|
||||||
defp parse_boolean("true"), do: true
|
|
||||||
defp parse_boolean("false"), do: false
|
|
||||||
defp parse_boolean(1), do: true
|
|
||||||
defp parse_boolean(0), do: false
|
|
||||||
defp parse_boolean(_), do: false
|
|
||||||
|
|
||||||
defp format_error(%Ash.Error.Invalid{} = error) do
|
defp format_error(%Ash.Error.Invalid{} = error) do
|
||||||
Ash.ErrorKind.message(error)
|
Ash.ErrorKind.message(error)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@ defmodule MvWeb.MemberFieldLive.IndexComponent do
|
||||||
"""
|
"""
|
||||||
use MvWeb, :live_component
|
use MvWeb, :live_component
|
||||||
|
|
||||||
|
alias Ash.Resource.Info
|
||||||
alias Mv.Membership
|
alias Mv.Membership
|
||||||
alias MvWeb.Translations.FieldTypes
|
alias Mv.Membership.Helpers.VisibilityConfig
|
||||||
|
alias MvWeb.Helpers.FieldTypeFormatter
|
||||||
alias MvWeb.Translations.MemberFields
|
alias MvWeb.Translations.MemberFields
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
|
|
@ -180,11 +182,11 @@ defmodule MvWeb.MemberFieldLive.IndexComponent do
|
||||||
visibility_config = settings.member_field_visibility || %{}
|
visibility_config = settings.member_field_visibility || %{}
|
||||||
|
|
||||||
# Normalize visibility config keys to atoms
|
# Normalize visibility config keys to atoms
|
||||||
normalized_config = normalize_visibility_config(visibility_config)
|
normalized_config = VisibilityConfig.normalize(visibility_config)
|
||||||
|
|
||||||
Enum.map(member_fields, fn field ->
|
Enum.map(member_fields, fn field ->
|
||||||
show_in_overview = Map.get(normalized_config, field, true)
|
show_in_overview = Map.get(normalized_config, field, true)
|
||||||
attribute = Ash.Resource.Info.attribute(Mv.Membership.Member, field)
|
attribute = Info.attribute(Mv.Membership.Member, field)
|
||||||
|
|
||||||
%{
|
%{
|
||||||
field: field,
|
field: field,
|
||||||
|
|
@ -199,68 +201,15 @@ defmodule MvWeb.MemberFieldLive.IndexComponent do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp format_value_type(field) when is_atom(field) do
|
defp format_value_type(field) when is_atom(field) do
|
||||||
case Ash.Resource.Info.attribute(Mv.Membership.Member, field) do
|
case Info.attribute(Mv.Membership.Member, field) do
|
||||||
nil -> FieldTypes.label(:string)
|
nil -> FieldTypeFormatter.format(:string)
|
||||||
attribute -> format_value_type(attribute.type)
|
attribute -> FieldTypeFormatter.format(attribute.type)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp format_value_type(type) when is_atom(type) do
|
|
||||||
type_string = to_string(type)
|
|
||||||
|
|
||||||
# Check if it's an Ash type module (e.g., Ash.Type.String or Elixir.Ash.Type.String)
|
|
||||||
if String.contains?(type_string, "Ash.Type.") do
|
|
||||||
# Extract the base type name from Ash type modules
|
|
||||||
# e.g., "Elixir.Ash.Type.String" -> "String" -> :string
|
|
||||||
type_name =
|
|
||||||
type_string
|
|
||||||
|> String.split(".")
|
|
||||||
|> List.last()
|
|
||||||
|> String.downcase()
|
|
||||||
|
|
||||||
try do
|
|
||||||
type_atom = String.to_existing_atom(type_name)
|
|
||||||
FieldTypes.label(type_atom)
|
|
||||||
rescue
|
|
||||||
ArgumentError ->
|
|
||||||
# Fallback if atom doesn't exist
|
|
||||||
FieldTypes.label(:string)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
# It's already an atom like :string, :boolean, :date
|
|
||||||
FieldTypes.label(type)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp format_value_type(type) do
|
|
||||||
# Fallback for unknown types
|
|
||||||
to_string(type)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp normalize_visibility_config(config) when is_map(config) do
|
|
||||||
Enum.reduce(config, %{}, fn
|
|
||||||
{key, value}, acc when is_atom(key) ->
|
|
||||||
Map.put(acc, key, value)
|
|
||||||
|
|
||||||
{key, value}, acc when is_binary(key) ->
|
|
||||||
try do
|
|
||||||
atom_key = String.to_existing_atom(key)
|
|
||||||
Map.put(acc, atom_key, value)
|
|
||||||
rescue
|
|
||||||
ArgumentError ->
|
|
||||||
acc
|
|
||||||
end
|
|
||||||
|
|
||||||
_, acc ->
|
|
||||||
acc
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp normalize_visibility_config(_), do: %{}
|
|
||||||
|
|
||||||
# Check if a field is required by checking the actual attribute definition
|
# Check if a field is required by checking the actual attribute definition
|
||||||
defp required?(field) when is_atom(field) do
|
defp required?(field) when is_atom(field) do
|
||||||
case Ash.Resource.Info.attribute(Mv.Membership.Member, field) do
|
case Info.attribute(Mv.Membership.Member, field) do
|
||||||
nil -> false
|
nil -> false
|
||||||
attribute -> not attribute.allow_nil?
|
attribute -> not attribute.allow_nil?
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ defmodule MvWeb.MemberLive.Index.FieldVisibility do
|
||||||
3. Default (all fields visible)
|
3. Default (all fields visible)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
alias Mv.Membership.Helpers.VisibilityConfig
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Gets all available fields for selection.
|
Gets all available fields for selection.
|
||||||
|
|
||||||
|
|
@ -177,7 +179,7 @@ defmodule MvWeb.MemberLive.Index.FieldVisibility do
|
||||||
# Gets member field visibility from settings
|
# Gets member field visibility from settings
|
||||||
defp get_member_field_visibility_from_settings(settings) do
|
defp get_member_field_visibility_from_settings(settings) do
|
||||||
visibility_config =
|
visibility_config =
|
||||||
normalize_visibility_config(Map.get(settings, :member_field_visibility, %{}))
|
VisibilityConfig.normalize(Map.get(settings, :member_field_visibility, %{}))
|
||||||
|
|
||||||
member_fields = Mv.Constants.member_fields()
|
member_fields = Mv.Constants.member_fields()
|
||||||
|
|
||||||
|
|
@ -201,27 +203,6 @@ defmodule MvWeb.MemberLive.Index.FieldVisibility do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Normalizes visibility config map keys from strings to atoms
|
|
||||||
defp normalize_visibility_config(config) when is_map(config) do
|
|
||||||
Enum.reduce(config, %{}, fn
|
|
||||||
{key, value}, acc when is_atom(key) ->
|
|
||||||
Map.put(acc, key, value)
|
|
||||||
|
|
||||||
{key, value}, acc when is_binary(key) ->
|
|
||||||
try do
|
|
||||||
atom_key = String.to_existing_atom(key)
|
|
||||||
Map.put(acc, atom_key, value)
|
|
||||||
rescue
|
|
||||||
ArgumentError -> acc
|
|
||||||
end
|
|
||||||
|
|
||||||
_, acc ->
|
|
||||||
acc
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp normalize_visibility_config(_), do: %{}
|
|
||||||
|
|
||||||
# Converts field string to atom (for member fields) or keeps as string (for custom fields)
|
# Converts field string to atom (for member fields) or keeps as string (for custom fields)
|
||||||
defp to_field_identifier(field_string) when is_binary(field_string) do
|
defp to_field_identifier(field_string) when is_binary(field_string) do
|
||||||
if String.starts_with?(field_string, Mv.Constants.custom_field_prefix()) do
|
if String.starts_with?(field_string, Mv.Constants.custom_field_prefix()) do
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue