Add basic metadata to opengraph preview
Also refactor datetime & address utils Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -5,6 +5,7 @@ defmodule Mobilizon.Cldr do
|
||||
|
||||
use Cldr,
|
||||
locales: Application.get_env(:mobilizon, :cldr)[:locales],
|
||||
add_fallback_locales: true,
|
||||
gettext:
|
||||
if(Application.fetch_env!(:mobilizon, :env) == :prod,
|
||||
do: Mobilizon.Web.Gettext,
|
||||
|
||||
95
lib/service/address/address.ex
Normal file
95
lib/service/address/address.ex
Normal file
@@ -0,0 +1,95 @@
|
||||
defmodule Mobilizon.Service.Address do
|
||||
@moduledoc """
|
||||
Module to render an `Mobilizon.Addresses.Address` struct to a string
|
||||
"""
|
||||
|
||||
alias Mobilizon.Addresses.Address, as: AddressModel
|
||||
|
||||
@type address :: %{name: String.t(), alternative_name: String.t()}
|
||||
|
||||
def render_address(%AddressModel{} = address) do
|
||||
%{name: name, alternative_name: alternative_name} = render_names(address)
|
||||
|
||||
cond do
|
||||
defined?(alternative_name) && defined?(name) ->
|
||||
"#{name}, #{alternative_name}"
|
||||
|
||||
defined?(name) ->
|
||||
name
|
||||
|
||||
defined?(alternative_name) ->
|
||||
alternative_name
|
||||
|
||||
true ->
|
||||
raise ArgumentError, message: "Invalid address"
|
||||
end
|
||||
end
|
||||
|
||||
@spec render_names(AddressModel.t()) :: address()
|
||||
def render_names(%AddressModel{type: nil} = address) do
|
||||
render_names(%AddressModel{address | type: "house"})
|
||||
end
|
||||
|
||||
def render_names(%AddressModel{
|
||||
type: type,
|
||||
description: description,
|
||||
postal_code: postal_code,
|
||||
locality: locality,
|
||||
country: country
|
||||
})
|
||||
when type in ["house", "street", "secondary"] do
|
||||
%{
|
||||
name: description,
|
||||
alternative_name: [postal_code, locality, country] |> Enum.filter(& &1) |> Enum.join(", ")
|
||||
}
|
||||
end
|
||||
|
||||
def render_names(%AddressModel{
|
||||
type: type,
|
||||
description: description,
|
||||
postal_code: postal_code,
|
||||
locality: locality,
|
||||
country: country
|
||||
})
|
||||
when type in ["zone", "city", "administrative"] do
|
||||
%{
|
||||
name: if(defined?(postal_code), do: "#{description} (#{postal_code})", else: description),
|
||||
alternative_name:
|
||||
[locality, country]
|
||||
|> Enum.filter(& &1)
|
||||
|> Enum.filter(&(&1 != description))
|
||||
|> Enum.join(", ")
|
||||
}
|
||||
end
|
||||
|
||||
def render_names(%AddressModel{
|
||||
description: description,
|
||||
street: street,
|
||||
region: region,
|
||||
locality: locality,
|
||||
country: country
|
||||
}) do
|
||||
alternative_name =
|
||||
cond do
|
||||
defined?(street) ->
|
||||
if defined?(locality), do: "#{street} (#{locality})", else: street
|
||||
|
||||
defined?(locality) ->
|
||||
"#{locality}, #{region}, #{country}"
|
||||
|
||||
defined?(region) ->
|
||||
"#{region}, #{country}"
|
||||
|
||||
defined?(country) ->
|
||||
country
|
||||
|
||||
true ->
|
||||
nil
|
||||
end
|
||||
|
||||
%{name: description, alternative_name: alternative_name}
|
||||
end
|
||||
|
||||
defp defined?(string) when is_binary(string), do: String.trim(string) != ""
|
||||
defp defined?(_), do: false
|
||||
end
|
||||
41
lib/service/date_time/date_time.ex
Normal file
41
lib/service/date_time/date_time.ex
Normal file
@@ -0,0 +1,41 @@
|
||||
defmodule Mobilizon.Service.DateTime do
|
||||
@moduledoc """
|
||||
Module to represent a datetime in a given locale
|
||||
"""
|
||||
alias Cldr.DateTime.Relative
|
||||
|
||||
def datetime_to_string(%DateTime{} = datetime, locale \\ "en", format \\ :medium) do
|
||||
Mobilizon.Cldr.DateTime.to_string!(datetime, format: format, locale: locale_or_default(locale))
|
||||
end
|
||||
|
||||
def datetime_to_time_string(%DateTime{} = datetime, locale \\ "en", format \\ :short) do
|
||||
Mobilizon.Cldr.Time.to_string!(datetime, format: format, locale: locale_or_default(locale))
|
||||
end
|
||||
|
||||
@spec datetime_tz_convert(DateTime.t(), String.t()) :: DateTime.t()
|
||||
def datetime_tz_convert(%DateTime{} = datetime, timezone) do
|
||||
case DateTime.shift_zone(datetime, timezone) do
|
||||
{:ok, datetime_with_user_tz} ->
|
||||
datetime_with_user_tz
|
||||
|
||||
_ ->
|
||||
datetime
|
||||
end
|
||||
end
|
||||
|
||||
@spec datetime_relative(DateTime.t(), String.t()) :: String.t()
|
||||
def datetime_relative(%DateTime{} = datetime, locale \\ "en") do
|
||||
Relative.to_string!(datetime, Mobilizon.Cldr,
|
||||
relative_to: DateTime.utc_now(),
|
||||
locale: locale_or_default(locale)
|
||||
)
|
||||
end
|
||||
|
||||
defp locale_or_default(locale) do
|
||||
if Mobilizon.Cldr.known_locale_name(locale) do
|
||||
locale
|
||||
else
|
||||
"en"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,19 +1,22 @@
|
||||
defimpl Mobilizon.Service.Metadata, for: Mobilizon.Events.Event do
|
||||
alias Phoenix.HTML
|
||||
alias Phoenix.HTML.Tag
|
||||
alias Mobilizon.Addresses.Address
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Web.JsonLD.ObjectView
|
||||
import Mobilizon.Service.Metadata.Utils, only: [process_description: 2, strip_tags: 1]
|
||||
|
||||
import Mobilizon.Service.Metadata.Utils,
|
||||
only: [process_description: 2, strip_tags: 1, datetime_to_string: 2, render_address: 1]
|
||||
|
||||
def build_tags(%Event{} = event, locale \\ "en") do
|
||||
event = Map.put(event, :description, process_description(event.description, locale))
|
||||
formatted_description = description(event, locale)
|
||||
|
||||
tags = [
|
||||
Tag.content_tag(:title, event.title <> " - Mobilizon"),
|
||||
Tag.tag(:meta, name: "description", content: event.description),
|
||||
Tag.tag(:meta, name: "description", content: process_description(event.description, locale)),
|
||||
Tag.tag(:meta, property: "og:title", content: event.title),
|
||||
Tag.tag(:meta, property: "og:url", content: event.url),
|
||||
Tag.tag(:meta, property: "og:description", content: event.description),
|
||||
Tag.tag(:meta, property: "og:description", content: formatted_description),
|
||||
Tag.tag(:meta, property: "og:type", content: "website"),
|
||||
# Tell Search Engines what's the origin
|
||||
Tag.tag(:link, rel: "canonical", href: event.url)
|
||||
@@ -45,4 +48,25 @@ defimpl Mobilizon.Service.Metadata, for: Mobilizon.Events.Event do
|
||||
|> ObjectView.render(%{event: %{event | title: strip_tags(title)}})
|
||||
|> Jason.encode!()
|
||||
end
|
||||
|
||||
defp description(
|
||||
%Event{
|
||||
description: description,
|
||||
begins_on: begins_on,
|
||||
physical_address: %Address{} = address
|
||||
},
|
||||
locale
|
||||
) do
|
||||
"#{datetime_to_string(begins_on, locale)} - #{render_address(address)} - #{process_description(description, locale)}"
|
||||
end
|
||||
|
||||
defp description(
|
||||
%Event{
|
||||
description: description,
|
||||
begins_on: begins_on
|
||||
},
|
||||
locale
|
||||
) do
|
||||
"#{datetime_to_string(begins_on, locale)} - #{process_description(description, locale)}"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,6 +3,7 @@ defmodule Mobilizon.Service.Metadata.Utils do
|
||||
Tools to convert tags to string.
|
||||
"""
|
||||
|
||||
alias Mobilizon.Service.{Address, DateTime}
|
||||
alias Mobilizon.Service.Formatter.HTML, as: HTMLFormatter
|
||||
alias Phoenix.HTML
|
||||
import Mobilizon.Web.Gettext
|
||||
@@ -52,6 +53,9 @@ defmodule Mobilizon.Service.Metadata.Utils do
|
||||
gettext("The event organizer didn't add any description.")
|
||||
end
|
||||
|
||||
defdelegate datetime_to_string(datetime, locale \\ "en", format \\ :medium), to: DateTime
|
||||
defdelegate render_address(address), to: Address
|
||||
|
||||
defp maybe_slice(description, limit) do
|
||||
if String.length(description) > limit do
|
||||
description
|
||||
|
||||
@@ -1,39 +1,15 @@
|
||||
defmodule Mobilizon.Web.EmailView do
|
||||
use Mobilizon.Web, :view
|
||||
|
||||
alias Cldr.DateTime.Relative
|
||||
alias Mobilizon.Service.DateTime, as: DateTimeRenderer
|
||||
import Mobilizon.Web.Gettext
|
||||
|
||||
def datetime_to_string(%DateTime{} = datetime, locale \\ "en", format \\ :medium) do
|
||||
with {:ok, string} <-
|
||||
Mobilizon.Cldr.DateTime.to_string(datetime, format: format, locale: locale) do
|
||||
string
|
||||
end
|
||||
end
|
||||
defdelegate datetime_to_string(datetime, locale \\ "en", format \\ :medium),
|
||||
to: DateTimeRenderer
|
||||
|
||||
def datetime_to_time_string(%DateTime{} = datetime, locale \\ "en", format \\ :hm) do
|
||||
with {:ok, string} <-
|
||||
Mobilizon.Cldr.DateTime.to_string(datetime, format: format, locale: locale) do
|
||||
string
|
||||
end
|
||||
end
|
||||
defdelegate datetime_to_time_string(datetime, locale \\ "en", format \\ :short),
|
||||
to: DateTimeRenderer
|
||||
|
||||
@spec datetime_tz_convert(DateTime.t(), String.t()) :: DateTime.t()
|
||||
def datetime_tz_convert(%DateTime{} = datetime, timezone) do
|
||||
case DateTime.shift_zone(datetime, timezone) do
|
||||
{:ok, datetime_with_user_tz} ->
|
||||
datetime_with_user_tz
|
||||
|
||||
_ ->
|
||||
datetime
|
||||
end
|
||||
end
|
||||
|
||||
@spec datetime_relative(DateTime.t(), String.t()) :: String.t()
|
||||
def datetime_relative(%DateTime{} = datetime, locale \\ "en") do
|
||||
Relative.to_string!(datetime, Mobilizon.Cldr,
|
||||
relative_to: DateTime.utc_now(),
|
||||
locale: locale
|
||||
)
|
||||
end
|
||||
defdelegate datetime_tz_convert(datetime, timezone), to: DateTimeRenderer
|
||||
defdelegate datetime_relative(datetime, locale \\ "en"), to: DateTimeRenderer
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user