refactor: move pure post-editor logic to BDS.UI.PostEditor for TUI reuse (issue #26, phase 3)
This commit is contained in:
123
lib/bds/ui/post_editor/persistence.ex
Normal file
123
lib/bds/ui/post_editor/persistence.ex
Normal file
@@ -0,0 +1,123 @@
|
||||
defmodule BDS.UI.PostEditor.Persistence do
|
||||
@moduledoc """
|
||||
Save/publish/discard workflow for post drafts, shared by the LiveView
|
||||
shell and the TUI (issue #26, phase 3). Routes canonical-language edits
|
||||
to the post itself and other languages to translations.
|
||||
"""
|
||||
|
||||
alias BDS.Posts
|
||||
alias BDS.Posts.Post
|
||||
alias BDS.UI.PostEditor.{Draft, Metadata}
|
||||
use Gettext, backend: BDS.Gettext
|
||||
|
||||
@spec persist(term(), term(), term(), term(), term()) :: term()
|
||||
def persist(%Post{} = post, draft, active_language, metadata, action) do
|
||||
canonical_language = Metadata.canonical_language(post, metadata)
|
||||
translations = Metadata.translations(post.id)
|
||||
|
||||
if Draft.editing_canonical_language?(
|
||||
translations,
|
||||
active_language,
|
||||
canonical_language
|
||||
) do
|
||||
post
|
||||
|> save_canonical_draft(draft, action)
|
||||
|> maybe_publish_post(post.id, action)
|
||||
else
|
||||
post.id
|
||||
|> save_translation_draft(active_language, draft)
|
||||
|> maybe_publish_translation(post.id, active_language, action)
|
||||
end
|
||||
end
|
||||
|
||||
@spec discard(term(), term(), term()) :: term()
|
||||
def discard(%Post{} = post, active_language, metadata) do
|
||||
canonical_language = Metadata.canonical_language(post, metadata)
|
||||
current_translations = Metadata.translations(post.id)
|
||||
|
||||
cond do
|
||||
not Draft.editing_canonical_language?(
|
||||
current_translations,
|
||||
active_language,
|
||||
canonical_language
|
||||
) ->
|
||||
{:ok, post}
|
||||
|
||||
post.file_path not in [nil, ""] and post.status == :draft ->
|
||||
Posts.discard_post_changes(post.id)
|
||||
|
||||
true ->
|
||||
{:ok, post}
|
||||
end
|
||||
end
|
||||
|
||||
@spec has_published_version?(term()) :: term()
|
||||
def has_published_version?(%Post{} = post),
|
||||
do: not is_nil(post.published_at) or post.file_path not in [nil, ""]
|
||||
|
||||
@spec discard_label(term()) :: term()
|
||||
def discard_label(%Post{} = post) do
|
||||
if has_published_version?(post),
|
||||
do: dgettext("ui", "Discard Changes"),
|
||||
else: dgettext("ui", "Discard Draft")
|
||||
end
|
||||
|
||||
@spec discard_title(term()) :: term()
|
||||
def discard_title(%Post{} = post) do
|
||||
if has_published_version?(post),
|
||||
do: dgettext("ui", "Discard changes and restore the published version"),
|
||||
else: dgettext("ui", "Delete this unpublished draft")
|
||||
end
|
||||
|
||||
defp save_canonical_draft(%Post{id: post_id}, draft, action) do
|
||||
Posts.update_post(
|
||||
post_id,
|
||||
%{
|
||||
title: blank_to_nil(Map.get(draft, "title")),
|
||||
excerpt: blank_to_nil(Map.get(draft, "excerpt")),
|
||||
content: blank_to_nil(Map.get(draft, "content")),
|
||||
tags: csv_to_list(Map.get(draft, "tags")),
|
||||
categories: csv_to_list(Map.get(draft, "categories")),
|
||||
author: blank_to_nil(Map.get(draft, "author")),
|
||||
language: blank_to_nil(Map.get(draft, "language")),
|
||||
do_not_translate: Map.get(draft, "do_not_translate", false),
|
||||
template_slug: blank_to_nil(Map.get(draft, "template_slug"))
|
||||
},
|
||||
auto_translate: action != :auto_save
|
||||
)
|
||||
end
|
||||
|
||||
defp save_translation_draft(post_id, language, draft) do
|
||||
Posts.upsert_post_translation(post_id, language, %{
|
||||
title: Map.get(draft, "title", ""),
|
||||
excerpt: blank_to_nil(Map.get(draft, "excerpt")),
|
||||
content: blank_to_nil(Map.get(draft, "content"))
|
||||
})
|
||||
end
|
||||
|
||||
defp maybe_publish_post({:ok, %Post{}}, post_id, :publish), do: Posts.publish_post(post_id)
|
||||
defp maybe_publish_post(result, _post_id, _action), do: result
|
||||
|
||||
defp maybe_publish_translation({:ok, _translation}, post_id, language, :publish),
|
||||
do: Posts.publish_post_translation(post_id, language)
|
||||
|
||||
defp maybe_publish_translation(result, _post_id, _language, _action), do: result
|
||||
|
||||
defp blank_to_nil(value) do
|
||||
value
|
||||
|> to_string()
|
||||
|> String.trim()
|
||||
|> case do
|
||||
"" -> nil
|
||||
trimmed -> trimmed
|
||||
end
|
||||
end
|
||||
|
||||
defp csv_to_list(value) do
|
||||
value
|
||||
|> to_string()
|
||||
|> String.split(",")
|
||||
|> Enum.map(&String.trim/1)
|
||||
|> Enum.reject(&(&1 == ""))
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user