Packages

phoenix_kit

1.5.2
1.7.210 1.7.209 1.7.208 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
phoenix_kit lib phoenix_kit_web live modules blogging index.ex
Raw

lib/phoenix_kit_web/live/modules/blogging/index.ex

defmodule PhoenixKitWeb.Live.Modules.Blogging.Index do
@moduledoc """
Blogging module overview dashboard.
Provides high-level stats, quick actions, and guidance for administrators.
"""
use PhoenixKitWeb, :live_view
use Gettext, backend: PhoenixKitWeb.Gettext
alias PhoenixKit.Settings
alias PhoenixKit.Utils.Routes
alias PhoenixKitWeb.Live.Modules.Blogging
alias PhoenixKitWeb.Live.Modules.Blogging.Storage
def mount(params, _session, socket) do
locale = params["locale"] || socket.assigns[:current_locale] || "en"
Gettext.put_locale(PhoenixKitWeb.Gettext, locale)
Process.put(:phoenix_kit_current_locale, locale)
{blogs, insights, summary} = dashboard_snapshot(locale)
socket =
socket
|> assign(:current_locale, locale)
|> assign(:project_title, Settings.get_setting("project_title", "PhoenixKit"))
|> assign(:page_title, gettext("Blogging"))
|> assign(:current_path, Routes.path("/admin/blogging", locale: locale))
|> assign(:blogs, blogs)
|> assign(:dashboard_insights, insights)
|> assign(:dashboard_summary, summary)
|> assign(:empty_state?, blogs == [])
|> assign(:enabled_languages, Storage.enabled_language_codes())
|> assign(:endpoint_url, nil)
{:ok, socket}
end
def handle_params(_params, uri, socket) do
{blogs, insights, summary} = dashboard_snapshot(socket.assigns.current_locale)
endpoint_url = extract_endpoint_url(uri)
{:noreply,
assign(socket,
blogs: blogs,
dashboard_insights: insights,
dashboard_summary: summary,
empty_state?: blogs == [],
endpoint_url: endpoint_url
)}
end
defp dashboard_snapshot(locale) do
blogs = Blogging.list_blogs()
insights = Enum.map(blogs, &build_blog_insight(&1, locale))
summary = build_summary(blogs, insights)
{blogs, insights, summary}
end
defp build_blog_insight(blog, locale) do
posts = Blogging.list_posts(blog["slug"], locale)
status_counts = Enum.frequencies_by(posts, &Map.get(&1.metadata, :status, "draft"))
languages =
posts
|> Enum.flat_map(&(&1.available_languages || []))
|> Enum.uniq()
|> Enum.sort()
latest_published_at = find_latest_published_at(posts)
%{
name: blog["name"],
slug: blog["slug"],
mode: Map.get(blog, "mode", "timestamp"),
posts_count: length(posts),
published_count: Map.get(status_counts, "published", 0),
draft_count: Map.get(status_counts, "draft", 0),
archived_count: Map.get(status_counts, "archived", 0),
languages: languages,
last_published_at: latest_published_at,
last_published_at_text: format_datetime(latest_published_at)
}
end
defp find_latest_published_at(posts) do
posts
|> Enum.map(&Map.get(&1.metadata, :published_at))
|> Enum.reduce(nil, &update_latest_datetime/2)
end
defp update_latest_datetime(value, acc) do
case parse_datetime(value) do
{:ok, dt} -> compare_and_select_latest(dt, acc)
:error -> acc
end
end
defp compare_and_select_latest(datetime, nil), do: datetime
defp compare_and_select_latest(datetime, current) do
if DateTime.compare(datetime, current) == :gt, do: datetime, else: current
end
defp build_summary(blogs, insights) do
Enum.reduce(
insights,
%{
total_blogs: length(blogs),
total_posts: 0,
published_posts: 0,
draft_posts: 0,
archived_posts: 0
},
fn insight, acc ->
%{
acc
| total_posts: acc.total_posts + insight.posts_count,
published_posts: acc.published_posts + insight.published_count,
draft_posts: acc.draft_posts + insight.draft_count,
archived_posts: acc.archived_posts + insight.archived_count
}
end
)
end
defp parse_datetime(nil), do: :error
defp parse_datetime(value) when is_binary(value) do
case DateTime.from_iso8601(value) do
{:ok, dt, _offset} -> {:ok, dt}
_ -> :error
end
end
defp format_datetime(nil), do: nil
defp format_datetime(%DateTime{} = datetime) do
Calendar.strftime(DateTime.truncate(datetime, :second), "%B %d, %Y · %H:%M UTC")
rescue
_ -> nil
end
defp extract_endpoint_url(uri) when is_binary(uri) do
case URI.parse(uri) do
%URI{scheme: scheme, host: host, port: port} when not is_nil(scheme) and not is_nil(host) ->
port_string = if port in [80, 443], do: "", else: ":#{port}"
"#{scheme}://#{host}#{port_string}"
_ ->
""
end
end
defp extract_endpoint_url(_), do: ""
end