Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
10d3d03da1
10
.credo.exs
10
.credo.exs
|
@ -108,9 +108,10 @@
|
|||
{Credo.Check.Refactor.MatchInCondition, []},
|
||||
{Credo.Check.Refactor.NegatedConditionsInUnless, []},
|
||||
{Credo.Check.Refactor.NegatedConditionsWithElse, []},
|
||||
{Credo.Check.Refactor.Nesting, [
|
||||
max_nesting: 3
|
||||
]},
|
||||
{Credo.Check.Refactor.Nesting,
|
||||
[
|
||||
max_nesting: 3
|
||||
]},
|
||||
{Credo.Check.Refactor.PipeChainStart,
|
||||
[
|
||||
excluded_argument_types: [:atom, :binary, :fn, :keyword, :number],
|
||||
|
@ -159,8 +160,7 @@
|
|||
# Removed checks
|
||||
#
|
||||
{Credo.Check.Warning.LazyLogging, false},
|
||||
{Credo.Check.Refactor.MapInto, false},
|
||||
{Credo.Check.Warning.MissedMetadataKeyInLoggerConfig, false}
|
||||
{Credo.Check.Refactor.MapInto, false}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
npm run pre-commit
|
||||
|
|
|
@ -36,7 +36,7 @@ config :mobilizon, :instance,
|
|||
unconfirmed_user_grace_period_hours: 48,
|
||||
activity_expire_days: 365,
|
||||
activity_keep_number: 100,
|
||||
enable_instance_feeds: false,
|
||||
enable_instance_feeds: true,
|
||||
email_from: "noreply@localhost",
|
||||
email_reply_to: "noreply@localhost"
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Mobilizon instance configuration
|
||||
|
||||
import Config
|
||||
import Mobilizon.Service.Config.Helpers
|
||||
|
||||
{:ok, _} = Application.ensure_all_started(:tls_certificate_check)
|
||||
|
||||
|
@ -49,9 +50,20 @@ config :mobilizon, :instance,
|
|||
description: "Change this to a proper description of your instance",
|
||||
hostname: System.get_env("MOBILIZON_INSTANCE_HOST", "mobilizon.lan"),
|
||||
registrations_open: System.get_env("MOBILIZON_INSTANCE_REGISTRATIONS_OPEN", "false") == "true",
|
||||
demo: false,
|
||||
allow_relay: true,
|
||||
federating: true,
|
||||
registration_email_allowlist:
|
||||
System.get_env("MOBILIZON_INSTANCE_REGISTRATIONS_EMAIL_ALLOWLIST", "")
|
||||
|> String.split(",", trim: true),
|
||||
registration_email_denylist:
|
||||
System.get_env("MOBILIZON_INSTANCE_REGISTRATIONS_EMAIL_DENYLIST", "")
|
||||
|> String.split(",", trim: true),
|
||||
disable_database_login:
|
||||
System.get_env("MOBILIZON_INSTANCE_DISABLE_DATABASE_LOGIN", "false") == "true",
|
||||
default_language: System.get_env("MOBILIZON_INSTANCE_DEFAULT_LANGUAGE", "en"),
|
||||
demo: System.get_env("MOBILIZON_INSTANCE_DEMO", "false") == "true",
|
||||
allow_relay: System.get_env("MOBILIZON_INSTANCE_ALLOW_RELAY", "true") == "true",
|
||||
federating: System.get_env("MOBILIZON_INSTANCE_FEDERATING", "true") == "true",
|
||||
enable_instance_feeds:
|
||||
System.get_env("MOBILIZON_INSTANCE_ENABLE_INSTANCE_FEEDS", "true") == "true",
|
||||
email_from: System.get_env("MOBILIZON_INSTANCE_EMAIL", "noreply@mobilizon.lan"),
|
||||
email_reply_to: System.get_env("MOBILIZON_REPLY_EMAIL", "noreply@mobilizon.lan")
|
||||
|
||||
|
@ -79,7 +91,7 @@ config :mobilizon, Mobilizon.Web.Email.Mailer,
|
|||
ssl: System.get_env("MOBILIZON_SMTP_SSL", "false"),
|
||||
retries: 1,
|
||||
no_mx_lookups: false,
|
||||
auth: :if_available
|
||||
auth: System.get_env("MOBILIZON_SMTP_AUTH", "if_available")
|
||||
|
||||
config :geolix,
|
||||
databases: [
|
||||
|
@ -93,13 +105,30 @@ config :geolix,
|
|||
config :mobilizon, Mobilizon.Web.Upload.Uploader.Local,
|
||||
uploads: System.get_env("MOBILIZON_UPLOADS", "/var/lib/mobilizon/uploads")
|
||||
|
||||
formats =
|
||||
if System.get_env("MOBILIZON_EXPORTS_FORMAT_CSV_ENABLED", "true") == "true" do
|
||||
[Mobilizon.Service.Export.Participants.CSV]
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
||||
formats =
|
||||
if System.get_env("MOBILIZON_EXPORTS_FORMAT_PDF_ENABLED", "true") == "true" do
|
||||
formats ++ [Mobilizon.Service.Export.Participants.PDF]
|
||||
else
|
||||
formats
|
||||
end
|
||||
|
||||
formats =
|
||||
if System.get_env("MOBILIZON_EXPORTS_FORMAT_ODS_ENABLED", "true") == "true" do
|
||||
formats ++ [Mobilizon.Service.Export.Participants.ODS]
|
||||
else
|
||||
formats
|
||||
end
|
||||
|
||||
config :mobilizon, :exports,
|
||||
path: System.get_env("MOBILIZON_UPLOADS_EXPORTS", "/var/lib/mobilizon/uploads/exports"),
|
||||
formats: [
|
||||
Mobilizon.Service.Export.Participants.CSV,
|
||||
Mobilizon.Service.Export.Participants.PDF,
|
||||
Mobilizon.Service.Export.Participants.ODS
|
||||
]
|
||||
formats: formats
|
||||
|
||||
config :tz_world,
|
||||
data_dir: System.get_env("MOBILIZON_TIMEZONES_DIR", "/var/lib/mobilizon/timezones")
|
||||
|
@ -110,3 +139,131 @@ config :web_push_encryption, :vapid_details,
|
|||
subject: System.get_env("MOBILIZON_WEB_PUSH_ENCRYPTION_SUBJECT", nil),
|
||||
public_key: System.get_env("MOBILIZON_WEB_PUSH_ENCRYPTION_PUBLIC_KEY", nil),
|
||||
private_key: System.get_env("MOBILIZON_WEB_PUSH_ENCRYPTION_PRIVATE_KEY", nil)
|
||||
|
||||
geospatial_service =
|
||||
case System.get_env("MOBILIZON_GEOSPATIAL_SERVICE", "Nominatim") do
|
||||
"Nominatim" -> Mobilizon.Service.Geospatial.Nominatim
|
||||
"Addok" -> Mobilizon.Service.Geospatial.Addok
|
||||
"Photon" -> Mobilizon.Service.Geospatial.Photon
|
||||
"GoogleMaps" -> Mobilizon.Service.Geospatial.GoogleMaps
|
||||
"MapQuest" -> Mobilizon.Service.Geospatial.MapQuest
|
||||
"Mimirsbrunn" -> Mobilizon.Service.Geospatial.Mimirsbrunn
|
||||
"Pelias" -> Mobilizon.Service.Geospatial.Pelias
|
||||
end
|
||||
|
||||
config :mobilizon, Mobilizon.Service.Geospatial, service: geospatial_service
|
||||
|
||||
if System.get_env("MOBILIZON_GEOSPATIAL_SERVICE", "Nominatim") == "Nominatim" do
|
||||
config :mobilizon, Mobilizon.Service.Geospatial.Nominatim,
|
||||
endpoint:
|
||||
System.get_env(
|
||||
"MOBILIZON_GEOSPATIAL_NOMINATIM_ENDPOINT",
|
||||
"https://nominatim.openstreetmap.org"
|
||||
),
|
||||
api_key: System.get_env("MOBILIZON_GEOSPATIAL_NOMINATIM_API_KEY", nil)
|
||||
end
|
||||
|
||||
if System.get_env("MOBILIZON_GEOSPATIAL_SERVICE", "Nominatim") == "Addok" do
|
||||
config :mobilizon, Mobilizon.Service.Geospatial.Addok,
|
||||
endpoint:
|
||||
System.get_env("MOBILIZON_GEOSPATIAL_ADDOK_ENDPOINT", "https://api-adresse.data.gouv.fr")
|
||||
end
|
||||
|
||||
if System.get_env("MOBILIZON_GEOSPATIAL_SERVICE", "Nominatim") == "Photon" do
|
||||
config :mobilizon, Mobilizon.Service.Geospatial.Photon,
|
||||
endpoint: System.get_env("MOBILIZON_GEOSPATIAL_PHOTON_ENDPOINT", "https://photon.komoot.de")
|
||||
end
|
||||
|
||||
if System.get_env("MOBILIZON_GEOSPATIAL_SERVICE", "Nominatim") == "GoogleMaps" do
|
||||
config :mobilizon, Mobilizon.Service.Geospatial.GoogleMaps,
|
||||
api_key: System.get_env("MOBILIZON_GEOSPATIAL_GOOGLE_MAPS_API_KEY", nil),
|
||||
fetch_place_details: true
|
||||
end
|
||||
|
||||
if System.get_env("MOBILIZON_GEOSPATIAL_SERVICE", "Nominatim") == "MapQuest" do
|
||||
config :mobilizon, Mobilizon.Service.Geospatial.MapQuest,
|
||||
api_key: System.get_env("MOBILIZON_GEOSPATIAL_MAP_QUEST_API_KEY", nil)
|
||||
end
|
||||
|
||||
if System.get_env("MOBILIZON_GEOSPATIAL_SERVICE", "Nominatim") == "Mimirsbrunn" do
|
||||
config :mobilizon, Mobilizon.Service.Geospatial.Mimirsbrunn,
|
||||
endpoint: System.get_env("MOBILIZON_GEOSPATIAL_MIMIRSBRUNN_ENDPOINT", nil)
|
||||
end
|
||||
|
||||
if System.get_env("MOBILIZON_GEOSPATIAL_SERVICE", "Nominatim") == "Pelias" do
|
||||
config :mobilizon, Mobilizon.Service.Geospatial.Pelias,
|
||||
endpoint: System.get_env("MOBILIZON_GEOSPATIAL_PELIAS_ENDPOINT", nil)
|
||||
end
|
||||
|
||||
sentry_dsn = System.get_env("MOBILIZON_ERROR_REPORTING_SENTRY_DSN", nil)
|
||||
|
||||
included_environments = if sentry_dsn, do: ["prod"], else: []
|
||||
|
||||
config :sentry,
|
||||
dsn: sentry_dsn,
|
||||
included_environments: included_environments,
|
||||
release: to_string(Application.spec(:mobilizon, :vsn))
|
||||
|
||||
config :logger, Sentry.LoggerBackend,
|
||||
capture_log_messages: true,
|
||||
level: :error
|
||||
|
||||
if sentry_dsn != nil do
|
||||
config :mobilizon, Mobilizon.Service.ErrorReporting,
|
||||
adapter: Mobilizon.Service.ErrorReporting.Sentry
|
||||
end
|
||||
|
||||
matomo_enabled = System.get_env("MOBILIZON_FRONT_END_ANALYTICS_MATOMO_ENABLED", "false") == "true"
|
||||
matomo_endpoint = System.get_env("MOBILIZON_FRONT_END_ANALYTICS_MATOMO_ENDPOINT", nil)
|
||||
matomo_site_id = System.get_env("MOBILIZON_FRONT_END_ANALYTICS_MATOMO_SITE_ID", nil)
|
||||
|
||||
matomo_tracker_file_name =
|
||||
System.get_env("MOBILIZON_FRONT_END_ANALYTICS_MATOMO_TRACKER_FILE_NAME", "matomo")
|
||||
|
||||
matomo_host = host_from_uri(matomo_endpoint)
|
||||
|
||||
analytics_providers =
|
||||
if matomo_enabled do
|
||||
[Mobilizon.Service.FrontEndAnalytics.Matomo]
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
||||
analytics_providers =
|
||||
if sentry_dsn != nil do
|
||||
analytics_providers ++ [Mobilizon.Service.FrontEndAnalytics.Sentry]
|
||||
else
|
||||
analytics_providers
|
||||
end
|
||||
|
||||
config :mobilizon, :analytics, providers: analytics_providers
|
||||
|
||||
matomo_csp =
|
||||
if matomo_enabled and matomo_host do
|
||||
[
|
||||
connect_src: [matomo_host],
|
||||
script_src: [matomo_host],
|
||||
img_src: [matomo_host]
|
||||
]
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
||||
config :mobilizon, Mobilizon.Service.FrontEndAnalytics.Matomo,
|
||||
enabled: matomo_enabled,
|
||||
host: matomo_endpoint,
|
||||
siteId: matomo_site_id,
|
||||
trackerFileName: matomo_tracker_file_name,
|
||||
csp: matomo_csp
|
||||
|
||||
config :mobilizon, Mobilizon.Service.FrontEndAnalytics.Sentry,
|
||||
enabled: sentry_dsn != nil,
|
||||
dsn: sentry_dsn,
|
||||
tracesSampleRate: 1.0,
|
||||
organization: System.get_env("MOBILIZON_ERROR_REPORTING_SENTRY_ORGANISATION", nil),
|
||||
project: System.get_env("MOBILIZON_ERROR_REPORTING_SENTRY_PROJECT", nil),
|
||||
host: System.get_env("MOBILIZON_ERROR_REPORTING_SENTRY_HOST", nil),
|
||||
csp: [
|
||||
connect_src:
|
||||
System.get_env("MOBILIZON_ERROR_REPORTING_SENTRY_HOST", "") |> String.split(" ", trim: true)
|
||||
]
|
||||
|
|
|
@ -61,8 +61,8 @@ mixRelease rec {
|
|||
src = fetchFromGitHub {
|
||||
owner = "danhper";
|
||||
repo = "elixir-web-push-encryption";
|
||||
rev = "70f00d06cbd88c9ac382e0ad2539e54448e9d8da";
|
||||
sha256 = "sha256-b4ZMrt/8n2sPUFtCDRTwXS1qWm5VlYdbx8qC0R0boOA=";
|
||||
rev = "6e143dcde0a2854c4f0d72816b7ecab696432779";
|
||||
sha256 = "sha256-Da+/28SPZuUQBi8fQj31zmMvhMrYUaQIW4U4E+mRtMg=";
|
||||
};
|
||||
beamDeps = with final; [ httpoison jose ];
|
||||
};
|
||||
|
|
|
@ -71,8 +71,10 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
|
|||
case Discussions.get_comment_from_url_with_preload(object["id"]) do
|
||||
{:error, :comment_not_found} ->
|
||||
case Converter.Comment.as_to_model_data(object) do
|
||||
%{visibility: visibility, attributed_to_id: attributed_to_id} = object_data
|
||||
when visibility === :private and is_nil(attributed_to_id) ->
|
||||
%{visibility: visibility, attributed_to_id: attributed_to_id, actor_id: actor_id} =
|
||||
object_data
|
||||
when visibility === :private and
|
||||
(is_nil(attributed_to_id) or actor_id == attributed_to_id) ->
|
||||
Actions.Create.create(:conversation, object_data, false)
|
||||
|
||||
object_data when is_map(object_data) ->
|
||||
|
|
|
@ -6,10 +6,13 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||
internal one, and back.
|
||||
"""
|
||||
|
||||
alias Cldr.DateTime.Formatter
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Addresses.Address
|
||||
alias Mobilizon.Events.Categories
|
||||
alias Mobilizon.Events.Event, as: EventModel
|
||||
alias Mobilizon.Events.EventOptions
|
||||
alias Mobilizon.Medias.Media
|
||||
|
||||
alias Mobilizon.Federation.ActivityStream.{Converter, Convertible}
|
||||
|
@ -29,7 +32,14 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||
maybe_fetch_actor_and_attributed_to_id: 1,
|
||||
process_pictures: 2,
|
||||
get_address: 1,
|
||||
fetch_actor: 1
|
||||
fetch_actor: 1,
|
||||
visibility_public?: 1
|
||||
]
|
||||
|
||||
import Mobilizon.Service.Metadata.Utils,
|
||||
only: [
|
||||
datetime_to_string: 3,
|
||||
render_address!: 1
|
||||
]
|
||||
|
||||
require Logger
|
||||
|
@ -146,7 +156,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||
"anonymousParticipationEnabled" => event.options.anonymous_participation,
|
||||
"attachment" => Enum.map(event.metadata, &EventMetadataConverter.metadata_to_as/1),
|
||||
"draft" => event.draft,
|
||||
# Remove me in MBZ 5.x
|
||||
# TODO: Remove me in MBZ 5.x
|
||||
"ical:status" => event.status |> to_string |> String.upcase(),
|
||||
"status" => event.status |> to_string |> String.upcase(),
|
||||
"id" => event.url,
|
||||
|
@ -154,7 +164,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||
"inLanguage" => event.language,
|
||||
"timezone" => event.options.timezone,
|
||||
"contacts" => Enum.map(event.contacts, & &1.url),
|
||||
"isOnline" => event.options.is_online
|
||||
"isOnline" => event.options.is_online,
|
||||
"summary" => event_summary(event)
|
||||
}
|
||||
|> maybe_add_physical_address(event)
|
||||
|> maybe_add_event_picture(event)
|
||||
|
@ -216,7 +227,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||
|
||||
defp get_metdata(_), do: []
|
||||
|
||||
defp get_visibility(object), do: if(@ap_public in object["to"], do: :public, else: :unlisted)
|
||||
defp get_visibility(object),
|
||||
do: if(visibility_public?(object["to"]), do: :public, else: :unlisted)
|
||||
|
||||
@spec date_to_string(DateTime.t() | nil) :: String.t()
|
||||
defp date_to_string(nil), do: nil
|
||||
|
@ -341,4 +353,47 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||
_participant_count
|
||||
),
|
||||
do: nil
|
||||
|
||||
def event_summary(%EventModel{
|
||||
begins_on: begins_on,
|
||||
physical_address: address,
|
||||
options: %EventOptions{timezone: timezone},
|
||||
language: language
|
||||
}) do
|
||||
begins_on = build_begins_on(begins_on, timezone)
|
||||
|
||||
begins_on
|
||||
|> datetime_to_string(language || "en", :long)
|
||||
|> (&[&1]).()
|
||||
|> add_timezone(begins_on)
|
||||
|> maybe_build_address(address)
|
||||
|> Enum.join(" - ")
|
||||
end
|
||||
|
||||
@spec build_begins_on(DateTime.t(), String.t() | nil) :: DateTime.t()
|
||||
defp build_begins_on(begins_on, nil), do: begins_on
|
||||
|
||||
defp build_begins_on(begins_on, timezone) do
|
||||
case DateTime.shift_zone(begins_on, timezone) do
|
||||
{:ok, begins_on} -> begins_on
|
||||
{:error, _err} -> begins_on
|
||||
end
|
||||
end
|
||||
|
||||
defp add_timezone(elements, %DateTime{} = begins_on) do
|
||||
elements ++ [Formatter.zone_gmt(begins_on)]
|
||||
end
|
||||
|
||||
@spec maybe_build_address(list(String.t()), Address.t() | nil) :: list(String.t())
|
||||
defp maybe_build_address(elements, %Address{} = address) do
|
||||
elements ++ [render_address!(address)]
|
||||
rescue
|
||||
# If the address is not renderable
|
||||
e in ArgumentError ->
|
||||
require Logger
|
||||
Logger.error(Exception.format(:error, e, __STACKTRACE__))
|
||||
elements
|
||||
end
|
||||
|
||||
defp maybe_build_address(elements, _address), do: elements
|
||||
end
|
||||
|
|
|
@ -15,7 +15,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Post do
|
|||
|
||||
import Mobilizon.Federation.ActivityStream.Converter.Utils,
|
||||
only: [
|
||||
process_pictures: 2
|
||||
process_pictures: 2,
|
||||
visibility_public?: 1
|
||||
]
|
||||
|
||||
import Mobilizon.Service.Guards, only: [is_valid_string: 1]
|
||||
|
@ -134,14 +135,12 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Post do
|
|||
)
|
||||
end
|
||||
|
||||
@ap_public "https://www.w3.org/ns/activitystreams#Public"
|
||||
|
||||
defp get_visibility(%{"to" => to}, %Actor{
|
||||
followers_url: followers_url,
|
||||
members_url: members_url
|
||||
}) do
|
||||
cond do
|
||||
@ap_public in to -> :public
|
||||
visibility_public?(to) -> :public
|
||||
followers_url in to -> :unlisted
|
||||
members_url in to -> :private
|
||||
end
|
||||
|
|
|
@ -205,9 +205,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do
|
|||
|
||||
@spec process_pictures(map(), integer()) :: Keyword.t()
|
||||
def process_pictures(object, actor_id) do
|
||||
attachements = Map.get(object, "attachment", [])
|
||||
|
||||
{banner, media_attachements} = get_medias(attachements)
|
||||
{banner, media_attachements} = get_medias(object)
|
||||
|
||||
media_attachements_map =
|
||||
media_attachements
|
||||
|
@ -259,24 +257,46 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do
|
|||
do: String.replace(body, old_url, new_url)
|
||||
|
||||
@spec get_medias(list(map())) :: {map(), list(map())}
|
||||
defp get_medias(attachments) do
|
||||
banner = get_banner_picture(attachments)
|
||||
{banner, Enum.filter(attachments, &(&1["type"] == "Document" && &1["url"] != banner["url"]))}
|
||||
def get_medias(object) do
|
||||
banner = get_banner_picture(object)
|
||||
attachments = Map.get(object, "attachment", [])
|
||||
{banner, Enum.filter(attachments, &(valid_banner_media?(&1) && &1["url"] != banner["url"]))}
|
||||
end
|
||||
|
||||
@spec get_banner_picture(list(map())) :: map()
|
||||
defp get_banner_picture(attachments) do
|
||||
# Prefer media with
|
||||
media_with_picture_name =
|
||||
Enum.find(attachments, &(&1["type"] == "Document" && &1["name"] == @banner_picture_name))
|
||||
@spec get_banner_picture(map()) :: map()
|
||||
defp get_banner_picture(object) do
|
||||
attachments = Map.get(object, "attachment", [])
|
||||
image = Map.get(object, "image", %{})
|
||||
|
||||
case media_with_picture_name do
|
||||
# If no banner found, use the first media
|
||||
nil -> Enum.find(attachments, &(&1["type"] == "Document"))
|
||||
media_with_picture_name -> media_with_picture_name
|
||||
media_with_picture_name =
|
||||
Enum.find(attachments, &(valid_banner_media?(&1) && &1["name"] == @banner_picture_name))
|
||||
|
||||
cond do
|
||||
# Check if the "image" key is set and of type "Document" or "Image"
|
||||
is_nil(media_with_picture_name) and valid_banner_media?(image) ->
|
||||
image
|
||||
|
||||
is_nil(media_with_picture_name) and Enum.find(attachments, &valid_banner_media?/1) ->
|
||||
Enum.find(attachments, &valid_banner_media?/1)
|
||||
|
||||
!is_nil(media_with_picture_name) ->
|
||||
media_with_picture_name
|
||||
|
||||
true ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@spec valid_banner_media?(map()) :: boolean()
|
||||
defp valid_banner_media?(media) do
|
||||
media |> Map.get("type") |> valid_attachment_type?()
|
||||
end
|
||||
|
||||
@spec valid_attachment_type?(any()) :: boolean()
|
||||
defp valid_attachment_type?(type) do
|
||||
type in ["Document", "Image"]
|
||||
end
|
||||
|
||||
@spec get_address(map | binary | nil) :: Address.t() | nil
|
||||
def get_address(text_address) when is_binary(text_address) do
|
||||
get_address(%{"type" => "Place", "name" => text_address})
|
||||
|
@ -315,4 +335,13 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do
|
|||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@ap_public "https://www.w3.org/ns/activitystreams#Public"
|
||||
|
||||
@spec visibility_public?(String.t() | list(String.t())) :: boolean()
|
||||
def visibility_public?(to) when is_binary(to), do: visibility_public?([to])
|
||||
|
||||
def visibility_public?(to) when is_list(to) do
|
||||
!MapSet.disjoint?(MapSet.new(to), MapSet.new([@ap_public, "as:Public", "Public"]))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -156,6 +156,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Conversation do
|
|||
|
||||
{:ok, conversation_to_view(conversation, conversation_participant_actor)}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:error, changeset}
|
||||
|
||||
{:error, :empty_participants} ->
|
||||
{:error,
|
||||
dgettext(
|
||||
|
|
|
@ -381,10 +381,15 @@ defmodule Mobilizon.GraphQL.Resolvers.Participant do
|
|||
visibility: :private
|
||||
})
|
||||
|
||||
with {:member, true} <-
|
||||
with {:ok,
|
||||
%Event{organizer_actor_id: organizer_actor_id, attributed_to_id: attributed_to_id} =
|
||||
_event} <- Mobilizon.Events.get_event(event_id),
|
||||
{:member, true} <-
|
||||
{:member,
|
||||
to_string(current_actor_id) == to_string(actor_id) or
|
||||
Actors.member?(current_actor_id, actor_id)},
|
||||
(to_string(current_actor_id) == to_string(organizer_actor_id) and
|
||||
to_string(current_actor_id) == to_string(actor_id)) or
|
||||
(!is_nil(attributed_to_id) and Actors.member?(current_actor_id, attributed_to_id) and
|
||||
to_string(attributed_to_id) == to_string(actor_id))},
|
||||
{:ok, _activity, %Conversation{} = conversation} <- Comments.create_conversation(args) do
|
||||
{:ok, conversation_to_view(conversation, Actors.get_actor(actor_id))}
|
||||
else
|
||||
|
|
|
@ -20,6 +20,7 @@ defmodule Mobilizon.GraphQL.Schema.ConversationType do
|
|||
)
|
||||
|
||||
field(:last_comment, :comment, description: "The last comment of the conversation")
|
||||
field(:origin_comment, :comment, description: "The first comment of the conversation")
|
||||
|
||||
field :comments, :paginated_comment_list do
|
||||
arg(:page, :integer, default_value: 1)
|
||||
|
|
|
@ -4,7 +4,7 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.CommentType do
|
|||
"""
|
||||
use Absinthe.Schema.Notation
|
||||
|
||||
import Absinthe.Resolution.Helpers, only: [dataloader: 1]
|
||||
import Absinthe.Resolution.Helpers, only: [dataloader: 1, dataloader: 2]
|
||||
|
||||
alias Mobilizon.{Actors, Discussions, Events}
|
||||
alias Mobilizon.GraphQL.Resolvers.Comment
|
||||
|
@ -23,7 +23,7 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.CommentType do
|
|||
|
||||
field(:replies, list_of(:comment)) do
|
||||
description("A list of replies to the comment")
|
||||
resolve(dataloader(Discussions))
|
||||
resolve(dataloader(Discussions, args: %{replies: true}))
|
||||
end
|
||||
|
||||
field(:total_replies, :integer,
|
||||
|
@ -47,6 +47,12 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.CommentType do
|
|||
|
||||
field(:threadLanguages, non_null(list_of(:string)), description: "The thread languages")
|
||||
field(:actor, :person, resolve: dataloader(Actors), description: "The comment's author")
|
||||
|
||||
field(:attributed_to, :actor,
|
||||
resolve: dataloader(Actors),
|
||||
description: "The comment's attributed to actor"
|
||||
)
|
||||
|
||||
field(:inserted_at, :datetime, description: "When was the comment inserted in database")
|
||||
field(:updated_at, :datetime, description: "When was the comment updated")
|
||||
field(:deleted_at, :datetime, description: "When was the comment deleted")
|
||||
|
|
|
@ -104,6 +104,10 @@ defmodule Mobilizon.Conversations do
|
|||
|> join(:inner, [_cp, _c, _e, _a, _lc, _oc, p], ap in Actor, on: p.actor_id == ap.id)
|
||||
|> where([_cp, c], c.event_id == ^event_id)
|
||||
|> where([cp], cp.actor_id == ^actor_id)
|
||||
|> where(
|
||||
[_cp, _c, _e, _a, _lc, oc],
|
||||
oc.actor_id == ^actor_id or oc.attributed_to_id == ^actor_id
|
||||
)
|
||||
|> order_by([cp], desc: cp.unread, desc: cp.updated_at)
|
||||
|> preload([_cp, c, e, a, lc, oc, p, ap],
|
||||
actor: a,
|
||||
|
@ -113,6 +117,14 @@ defmodule Mobilizon.Conversations do
|
|||
|> Page.build_page(page, limit)
|
||||
end
|
||||
|
||||
def find_all_conversations_for_event(event_id) do
|
||||
ConversationParticipant
|
||||
|> join(:inner, [cp], c in Conversation, on: cp.conversation_id == c.id)
|
||||
|> join(:left, [_cp, c], e in Event, on: c.event_id == e.id)
|
||||
|> where([_cp, c], c.event_id == ^event_id)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
@spec list_conversation_participants_for_actor(
|
||||
integer | String.t(),
|
||||
integer | nil,
|
||||
|
@ -133,7 +145,7 @@ defmodule Mobilizon.Conversations do
|
|||
subquery
|
||||
|> subquery()
|
||||
|> order_by([cp], desc: cp.unread, desc: cp.updated_at)
|
||||
|> preload([:actor, conversation: [:last_comment, :participants]])
|
||||
|> preload([:actor, conversation: [:last_comment, :origin_comment, :participants, :event]])
|
||||
|> Page.build_page(page, limit)
|
||||
end
|
||||
|
||||
|
@ -147,7 +159,7 @@ defmodule Mobilizon.Conversations do
|
|||
ConversationParticipant
|
||||
|> join(:inner, [cp], a in Actor, on: cp.actor_id == a.id)
|
||||
|> where([_cp, a], a.user_id == ^user_id)
|
||||
|> preload([:actor, conversation: [:last_comment, :participants]])
|
||||
|> preload([:actor, conversation: [:last_comment, :origin_comment, :participants, :event]])
|
||||
|> Page.build_page(page, limit)
|
||||
end
|
||||
|
||||
|
|
|
@ -85,6 +85,13 @@ defmodule Mobilizon.Discussions do
|
|||
|> select([c, r], %{c | total_replies: count(r.id)})
|
||||
end
|
||||
|
||||
# Replies are only used on event comments, so we always use public visibily here
|
||||
def query(Comment, %{replies: true}) do
|
||||
Comment
|
||||
|> where([c], c.visibility in ^@public_visibility)
|
||||
|> order_by([c], asc: :is_announcement, asc: :published_at)
|
||||
end
|
||||
|
||||
def query(Comment, _) do
|
||||
order_by(Comment, [c], asc: :is_announcement, asc: :published_at)
|
||||
end
|
||||
|
|
|
@ -792,7 +792,7 @@ defmodule Mobilizon.Events do
|
|||
end
|
||||
end
|
||||
|
||||
def get_participant(event_id, actor_id, %{}) do
|
||||
def get_participant(event_id, actor_id, _params) do
|
||||
case Participant
|
||||
|> Repo.get_by(event_id: event_id, actor_id: actor_id)
|
||||
|> Repo.preload(@participant_preloads) do
|
||||
|
|
|
@ -2,7 +2,7 @@ defmodule Mobilizon.Service.Activity.Conversation do
|
|||
@moduledoc """
|
||||
Insert a conversation activity
|
||||
"""
|
||||
alias Mobilizon.Conversations
|
||||
alias Mobilizon.{Actors, Conversations}
|
||||
alias Mobilizon.Conversations.{Conversation, ConversationParticipant}
|
||||
alias Mobilizon.Discussions.Comment
|
||||
alias Mobilizon.Events.Event
|
||||
|
@ -38,7 +38,7 @@ defmodule Mobilizon.Service.Activity.Conversation do
|
|||
%Conversation{
|
||||
id: conversation_id
|
||||
} = conversation,
|
||||
%Comment{actor_id: actor_id, text: last_comment_text},
|
||||
%Comment{actor_id: actor_id, text: last_comment_text} = comment,
|
||||
_options
|
||||
)
|
||||
when subject in [
|
||||
|
@ -55,7 +55,8 @@ defmodule Mobilizon.Service.Activity.Conversation do
|
|||
actor_id: conversation_participant_actor_id
|
||||
} =
|
||||
conversation_participant ->
|
||||
if actor_id != conversation_participant_actor_id do
|
||||
if actor_id != conversation_participant_actor_id and
|
||||
can_send_event_announcement?(conversation, comment) do
|
||||
LegacyNotifierBuilder.enqueue(
|
||||
:legacy_notify,
|
||||
%{
|
||||
|
@ -98,4 +99,31 @@ defmodule Mobilizon.Service.Activity.Conversation do
|
|||
}
|
||||
|
||||
defp event_subject_params(_), do: %{}
|
||||
|
||||
@spec can_send_event_announcement?(Conversation.t(), Comment.t()) :: boolean()
|
||||
defp can_send_event_announcement?(
|
||||
%Conversation{
|
||||
event: %Event{
|
||||
attributed_to_id: attributed_to_id
|
||||
}
|
||||
},
|
||||
%Comment{actor_id: actor_id}
|
||||
)
|
||||
when not is_nil(attributed_to_id) do
|
||||
attributed_to_id == actor_id or Actors.member?(actor_id, attributed_to_id)
|
||||
end
|
||||
|
||||
defp can_send_event_announcement?(
|
||||
%Conversation{
|
||||
event: %Event{
|
||||
organizer_actor_id: organizer_actor_id
|
||||
}
|
||||
},
|
||||
%Comment{actor_id: actor_id}
|
||||
)
|
||||
when not is_nil(organizer_actor_id) do
|
||||
organizer_actor_id == actor_id
|
||||
end
|
||||
|
||||
defp can_send_event_announcement?(_, _), do: false
|
||||
end
|
||||
|
|
|
@ -85,7 +85,7 @@ defmodule Mobilizon.Service.Address do
|
|||
defined?(street) ->
|
||||
if defined?(locality), do: "#{street} (#{locality})", else: street
|
||||
|
||||
defined?(locality) ->
|
||||
defined?(locality) and locality != region ->
|
||||
"#{locality}, #{region}, #{country}"
|
||||
|
||||
defined?(region) ->
|
||||
|
|
12
lib/service/config/helpers.ex
Normal file
12
lib/service/config/helpers.ex
Normal file
|
@ -0,0 +1,12 @@
|
|||
defmodule Mobilizon.Service.Config.Helpers do
|
||||
@moduledoc """
|
||||
Provide some helpers to configuration files
|
||||
"""
|
||||
|
||||
@spec host_from_uri(String.t() | nil) :: String.t() | nil
|
||||
def host_from_uri(nil), do: nil
|
||||
|
||||
def host_from_uri(uri) when is_binary(uri) do
|
||||
URI.parse(uri).host
|
||||
end
|
||||
end
|
|
@ -136,14 +136,12 @@ defimpl Mobilizon.Service.Metadata, for: Mobilizon.Events.Event do
|
|||
defp build_language(language, locale), do: language || locale
|
||||
|
||||
@spec build_begins_on(DateTime.t(), String.t() | nil) :: DateTime.t()
|
||||
defp build_begins_on(begins_on, nil), do: begins_on
|
||||
|
||||
defp build_begins_on(begins_on, timezone) do
|
||||
if timezone do
|
||||
case DateTime.shift_zone(begins_on, timezone) do
|
||||
{:ok, begins_on} -> begins_on
|
||||
{:error, _err} -> begins_on
|
||||
end
|
||||
else
|
||||
begins_on
|
||||
case DateTime.shift_zone(begins_on, timezone) do
|
||||
{:ok, begins_on} -> begins_on
|
||||
{:error, _err} -> begins_on
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ defmodule Mobilizon.Service.SiteMap do
|
|||
end)
|
||||
|> Sitemapper.generate(config)
|
||||
|> Sitemapper.persist(config)
|
||||
|> Sitemapper.ping(config)
|
||||
|> Stream.run()
|
||||
end,
|
||||
timeout: :infinity
|
||||
|
|
|
@ -4,7 +4,7 @@ defmodule Mobilizon.Service.Workers.LegacyNotifierBuilder do
|
|||
"""
|
||||
|
||||
alias Mobilizon.Activities.Activity
|
||||
alias Mobilizon.{Actors, Events, Users}
|
||||
alias Mobilizon.{Actors, Config, Events, Users}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.Service.Notifier
|
||||
|
@ -37,9 +37,10 @@ defmodule Mobilizon.Service.Workers.LegacyNotifierBuilder do
|
|||
end
|
||||
|
||||
defp special_handling("conversation_created", args, activity) do
|
||||
notify_participants(
|
||||
notify_participant(
|
||||
get_in(args, ["subject_params", "conversation_event_id"]),
|
||||
activity,
|
||||
get_in(args, ["participant", "actor_id"]),
|
||||
args["author_id"]
|
||||
)
|
||||
end
|
||||
|
@ -143,6 +144,24 @@ defmodule Mobilizon.Service.Workers.LegacyNotifierBuilder do
|
|||
notify_anonymous_participants(event_id, activity)
|
||||
end
|
||||
|
||||
defp notify_participant(nil, _activity, _conversation_participant_actor_id, _author_id),
|
||||
do: :ok
|
||||
|
||||
defp notify_participant(event_id, activity, conversation_participant_actor_id, author_id) do
|
||||
# Anonymous participation
|
||||
if conversation_participant_actor_id == Config.anonymous_actor_id() do
|
||||
notify_anonymous_participants(event_id, activity)
|
||||
else
|
||||
[conversation_participant_actor_id]
|
||||
|> users_from_actor_ids(author_id)
|
||||
|> Enum.each(fn user ->
|
||||
Notifier.Email.send_anonymous_activity(user.email, activity,
|
||||
locale: Map.get(user, :locale, "en")
|
||||
)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
defp notify_anonymous_participants(nil, _activity), do: :ok
|
||||
|
||||
defp notify_anonymous_participants(event_id, activity) do
|
||||
|
@ -154,7 +173,7 @@ defmodule Mobilizon.Service.Workers.LegacyNotifierBuilder do
|
|||
|> Enum.map(fn %Participant{metadata: metadata} -> metadata end)
|
||||
|> Enum.map(fn %{email: email} = metadata ->
|
||||
Notifier.Email.send_anonymous_activity(email, activity,
|
||||
locale: Map.get(metadata, :locale, "en")
|
||||
locale: Map.get(metadata, :locale, "en") || "en"
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
|
|
@ -95,7 +95,7 @@ defmodule Mobilizon.Web.Router do
|
|||
forward("/", Absinthe.Plug,
|
||||
schema: Mobilizon.GraphQL.Schema,
|
||||
analyze_complexity: true,
|
||||
max_complexity: 250
|
||||
max_complexity: 300
|
||||
)
|
||||
end
|
||||
|
||||
|
|
16
mix.exs
16
mix.exs
|
@ -121,10 +121,12 @@ defmodule Mobilizon.Mixfile do
|
|||
|> to_string()
|
||||
|> String.split()
|
||||
|> Enum.map(fn strategy_entry ->
|
||||
with [_strategy, dependency] <- String.split(strategy_entry, ":") do
|
||||
dependency
|
||||
else
|
||||
[strategy] -> "ueberauth_#{strategy}"
|
||||
case String.split(strategy_entry, ":") do
|
||||
[_strategy, dependency] ->
|
||||
dependency
|
||||
|
||||
[strategy] ->
|
||||
"ueberauth_#{strategy}"
|
||||
end
|
||||
end)
|
||||
|
||||
|
@ -185,7 +187,7 @@ defmodule Mobilizon.Mixfile do
|
|||
{:floki, "~> 0.31"},
|
||||
{:ip_reserved, "~> 0.1.0"},
|
||||
{:fast_sanitize, "~> 0.1"},
|
||||
{:ueberauth, "0.10.5", override: true},
|
||||
{:ueberauth, "0.10.7", override: true},
|
||||
{:ueberauth_twitter, "~> 0.4"},
|
||||
{:ueberauth_discord, "~> 0.7"},
|
||||
{:ueberauth_github, "~> 0.8.1"},
|
||||
|
@ -283,7 +285,7 @@ defmodule Mobilizon.Mixfile do
|
|||
File.rm_rf!("test/uploads")
|
||||
end
|
||||
|
||||
defp docs() do
|
||||
defp docs do
|
||||
[
|
||||
source_ref: "v#{@version}",
|
||||
groups_for_modules: groups_for_modules(),
|
||||
|
@ -323,7 +325,7 @@ defmodule Mobilizon.Mixfile do
|
|||
]
|
||||
end
|
||||
|
||||
defp groups_for_modules() do
|
||||
defp groups_for_modules do
|
||||
[
|
||||
Models: [
|
||||
~r/Mobilizon.Actors~r/,
|
||||
|
|
36
mix.lock
36
mix.lock
|
@ -14,10 +14,10 @@
|
|||
"comeonin": {:hex, :comeonin, "5.4.0", "246a56ca3f41d404380fc6465650ddaa532c7f98be4bda1b4656b3a37cc13abe", [:mix], [], "hexpm", "796393a9e50d01999d56b7b8420ab0481a7538d0caf80919da493b4a6e51faf1"},
|
||||
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
|
||||
"cors_plug": {:hex, :cors_plug, "3.0.3", "7c3ac52b39624bc616db2e937c282f3f623f25f8d550068b6710e58d04a0e330", [:mix], [{:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3f2d759e8c272ed3835fab2ef11b46bddab8c1ab9528167bd463b6452edf830d"},
|
||||
"cowboy": {:hex, :cowboy, "2.10.0", "ff9ffeff91dae4ae270dd975642997afe2a1179d94b1887863e43f681a203e26", [:make, :rebar3], [{:cowlib, "2.12.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "3afdccb7183cc6f143cb14d3cf51fa00e53db9ec80cdcd525482f5e99bc41d6b"},
|
||||
"cowboy": {:hex, :cowboy, "2.11.0", "356bf784599cf6f2cdc6ad12fdcfb8413c2d35dab58404cf000e1feaed3f5645", [:make, :rebar3], [{:cowlib, "2.12.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "0fa395437f1b0e104e0e00999f39d2ac5f4082ac5049b67a5b6d56ecc31b1403"},
|
||||
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
|
||||
"cowlib": {:hex, :cowlib, "2.12.1", "a9fa9a625f1d2025fe6b462cb865881329b5caff8f1854d1cbc9f9533f00e1e1", [:make, :rebar3], [], "hexpm", "163b73f6367a7341b33c794c4e88e7dbfe6498ac42dcd69ef44c5bc5507c8db0"},
|
||||
"credo": {:hex, :credo, "1.7.2", "fdee3a7cb553d8f2e773569181f0a4a2bb7d192e27e325404cc31b354f59d68c", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "dd15d6fbc280f6cf9b269f41df4e4992dee6615939653b164ef951f60afcb68e"},
|
||||
"credo": {:hex, :credo, "1.7.3", "05bb11eaf2f2b8db370ecaa6a6bda2ec49b2acd5e0418bc106b73b07128c0436", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "35ea675a094c934c22fb1dca3696f3c31f2728ae6ef5a53b5d648c11180a4535"},
|
||||
"credo_code_climate": {:hex, :credo_code_climate, "0.1.0", "1c4efbd11cb0244622ed5f09246b9afbbf796316ce03e78f67db6d81271d2978", [:mix], [{:credo, "~> 1.5", [hex: :credo, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "75529fe38056f4e229821d604758282838b8397c82e2c12e409fda16b16821ca"},
|
||||
"dataloader": {:hex, :dataloader, "2.0.0", "49b42d60b9bb06d761a71d7b034c4b34787957e713d4fae15387a25fcd639112", [:mix], [{:ecto, ">= 3.4.3 and < 4.0.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:opentelemetry_process_propagator, "~> 0.2.1", [hex: :opentelemetry_process_propagator, repo: "hexpm", optional: true]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "09d61781b76ce216e395cdbc883ff00d00f46a503e215c22722dba82507dfef0"},
|
||||
"db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"},
|
||||
|
@ -34,7 +34,7 @@
|
|||
"ecto_shortuuid": {:hex, :ecto_shortuuid, "0.2.0", "57cae7b6016cc56a04457b4fc8f63957398dfd9023ff3e900eaf6805a40f8043", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:shortuuid, "~> 2.1 or ~> 3.0", [hex: :shortuuid, repo: "hexpm", optional: false]}], "hexpm", "b92e3b71e86be92f5a7ef6f3de170e7864454e630f7b01dd930414baf38efb65"},
|
||||
"ecto_sql": {:hex, :ecto_sql, "3.11.1", "e9abf28ae27ef3916b43545f9578b4750956ccea444853606472089e7d169470", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ce14063ab3514424276e7e360108ad6c2308f6d88164a076aac8a387e1fea634"},
|
||||
"elixir_feed_parser": {:hex, :elixir_feed_parser, "2.1.0", "bb96fb6422158dc7ad59de62ef211cc69d264acbbe63941a64a5dce97bbbc2e6", [:mix], [{:timex, "~> 3.4", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm", "2d3c62fe7b396ee3b73d7160bc8fadbd78bfe9597c98c7d79b3f1038d9cba28f"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.7.8", "505026f266552ee5aabca0b9f9c229cbb496c689537c9f922f3eb5431157efc7", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "7a71945b913d37ea89b06966e1342c85cfe549b15e6d6d081e8081c493062c07"},
|
||||
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
|
||||
"erlport": {:hex, :erlport, "0.11.0", "8bb46a520e6eb9146e655fbf9b824433d9d532194667069d9aa45696aae9684b", [:rebar3], [], "hexpm", "8eb136ccaf3948d329b8d1c3278ad2e17e2a7319801bc4cc2da6db278204eee4"},
|
||||
"eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"},
|
||||
|
@ -43,9 +43,9 @@
|
|||
"ex_cldr_currencies": {:hex, :ex_cldr_currencies, "2.15.1", "e92ba17c41e7405b7784e0e65f406b5f17cfe313e0e70de9befd653e12854822", [:mix], [{:ex_cldr, "~> 2.34", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "31df8bd37688340f8819bdd770eb17d659652078d34db632b85d4a32864d6a25"},
|
||||
"ex_cldr_dates_times": {:hex, :ex_cldr_dates_times, "2.16.0", "d9848a5de83b6f1bcba151cc43d63b5c6311813cd605b1df1afd896dfdd21001", [:mix], [{:calendar_interval, "~> 0.2", [hex: :calendar_interval, repo: "hexpm", optional: true]}, {:ex_cldr_calendars, "~> 1.22", [hex: :ex_cldr_calendars, repo: "hexpm", optional: false]}, {:ex_cldr_numbers, "~> 2.31", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:tz, "~> 0.26", [hex: :tz, repo: "hexpm", optional: true]}], "hexpm", "0f2f250d479cadda4e0ef3a5e3d936ae7ba1a3f1199db6791e284e86203495b1"},
|
||||
"ex_cldr_languages": {:hex, :ex_cldr_languages, "0.3.3", "9787002803552b15a7ade19496c9e46fc921baca992ea80d0394e11fe3acea45", [:mix], [{:ex_cldr, "~> 2.25", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "22fb1fef72b7b4b4872d243b34e7b83734247a78ad87377986bf719089cc447a"},
|
||||
"ex_cldr_numbers": {:hex, :ex_cldr_numbers, "2.32.3", "b631ff94c982ec518e46bf4736000a30a33d6b58facc085d5f240305f512ad4a", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:digital_token, "~> 0.3 or ~> 1.0", [hex: :digital_token, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.37", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_currencies, ">= 2.14.2", [hex: :ex_cldr_currencies, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "7b626ff1e59a0ec9c3c5db5ce9ca91a6995e2ab56426b71f3cbf67181ea225f5"},
|
||||
"ex_cldr_numbers": {:hex, :ex_cldr_numbers, "2.32.4", "5562148dfc631b04712983975093d2aac29df30b3bf2f7257e0c94b85b72e91b", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:digital_token, "~> 0.3 or ~> 1.0", [hex: :digital_token, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.37", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_currencies, ">= 2.14.2", [hex: :ex_cldr_currencies, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "6fd5a82f0785418fa8b698c0be2b1845dff92b77f1b3172c763d37868fb503d2"},
|
||||
"ex_cldr_plugs": {:hex, :ex_cldr_plugs, "1.3.1", "ae58748df815ad21b8618830374a28b2ab593230e5df70ed9f647e953a884bec", [:mix], [{:ex_cldr, "~> 2.37", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:gettext, "~> 0.19", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "4f7b4a5fe061734cef7b62ff29118ed6ac72698cdd7bcfc97495db73611fe0fe"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.31.0", "06eb1dfd787445d9cab9a45088405593dd3bb7fe99e097eaa71f37ba80c7a676", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "5350cafa6b7f77bdd107aa2199fe277acf29d739aba5aee7e865fc680c62a110"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.31.1", "8a2355ac42b1cc7b2379da9e40243f2670143721dd50748bf6c3b1184dae2089", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "3178c3a407c557d8343479e1ff117a96fd31bafe52a039079593fb0524ef61b0"},
|
||||
"ex_ical": {:hex, :ex_ical, "0.2.0", "4b928b554614704016cc0c9ee226eb854da9327a1cc460457621ceacb1ac29a6", [:mix], [{:timex, "~> 3.1", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm", "db76473b2ae0259e6633c6c479a5a4d8603f09497f55c88f9ef4d53d2b75befb"},
|
||||
"ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"},
|
||||
"ex_optimizer": {:hex, :ex_optimizer, "0.1.1", "62da37e206fc2233ff7a4e54e40eae365c40f96c81992fcd15b782eb25169b80", [:mix], [{:file_info, "~> 0.0.4", [hex: :file_info, repo: "hexpm", optional: false]}], "hexpm", "e6f5c059bcd58b66be2f6f257fdc4f69b74b0fa5c9ddd669486af012e4b52286"},
|
||||
|
@ -55,11 +55,11 @@
|
|||
"exkismet": {:git, "https://github.com/tcitworld/exkismet.git", "8b5485fde00fafbde20f315bec387a77f7358334", []},
|
||||
"expo": {:hex, :expo, "0.5.1", "249e826a897cac48f591deba863b26c16682b43711dd15ee86b92f25eafd96d9", [:mix], [], "hexpm", "68a4233b0658a3d12ee00d27d37d856b1ba48607e7ce20fd376958d0ba6ce92b"},
|
||||
"export": {:hex, :export, "0.1.1", "6dfd268b0692428f89b9285859a2dc02b6dcd2e8fdfbca34ac6e6a331351df91", [:mix], [{:erlport, "~> 0.9", [hex: :erlport, repo: "hexpm", optional: false]}], "hexpm", "3da7444ff4053f1824352f4bdb13fbd2c28c93c2011786fb686b649fdca1021f"},
|
||||
"fast_html": {:hex, :fast_html, "2.2.0", "6c5ef1be087a4ed613b0379c13f815c4d11742b36b67bb52cee7859847c84520", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}], "hexpm", "064c4f23b4a6168f9187dac8984b056f2c531bb0787f559fd6a8b34b38aefbae"},
|
||||
"fast_html": {:hex, :fast_html, "2.3.0", "08c1d8ead840dd3060ba02c761bed9f37f456a1ddfe30bcdcfee8f651cec06a6", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}], "hexpm", "f18e3c7668f82d3ae0b15f48d48feeb257e28aa5ab1b0dbf781c7312e5da029d"},
|
||||
"fast_sanitize": {:hex, :fast_sanitize, "0.2.3", "67b93dfb34e302bef49fec3aaab74951e0f0602fd9fa99085987af05bd91c7a5", [:mix], [{:fast_html, "~> 2.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "e8ad286d10d0386e15d67d0ee125245ebcfbc7d7290b08712ba9013c8c5e56e2"},
|
||||
"file_info": {:hex, :file_info, "0.0.4", "2e0e77f211e833f38ead22cb29ce53761d457d80b3ffe0ffe0eb93880b0963b2", [:mix], [{:mimetype_parser, "~> 0.1.2", [hex: :mimetype_parser, repo: "hexpm", optional: false]}], "hexpm", "50e7ad01c2c8b9339010675fe4dc4a113b8d6ca7eddce24d1d74fd0e762781a5"},
|
||||
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||
"floki": {:hex, :floki, "0.35.2", "87f8c75ed8654b9635b311774308b2760b47e9a579dabf2e4d5f1e1d42c39e0b", [:mix], [], "hexpm", "6b05289a8e9eac475f644f09c2e4ba7e19201fd002b89c28c1293e7bd16773d9"},
|
||||
"floki": {:hex, :floki, "0.35.3", "0c8c6234aa71cb2b069cf801e8f8f30f8d096eb452c3dae2ccc409510ec32720", [:mix], [], "hexpm", "6d9f07f3fc76599f3b66c39f4a81ac62c8f4d9631140268db92aacad5d0e56d4"},
|
||||
"gen_smtp": {:hex, :gen_smtp, "1.2.0", "9cfc75c72a8821588b9b9fe947ae5ab2aed95a052b81237e0928633a13276fd3", [:rebar3], [{:ranch, ">= 1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "5ee0375680bca8f20c4d85f58c2894441443a743355430ff33a783fe03296779"},
|
||||
"geo": {:hex, :geo, "3.6.0", "00c9c6338579f67e91cd5950af4ae2eb25cdce0c3398718c232539f61625d0bd", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "1dbdebf617183b54bc3c8ad7a36531a9a76ada8ca93f75f573b0ae94006168da"},
|
||||
"geo_postgis": {:hex, :geo_postgis, "3.5.0", "e3675b6276b8c2166dc20a6fa9d992eb73c665de2b09b666d09c7824dc8a8300", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:geo, "~> 3.5", [hex: :geo, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "0bebc5b00f8b11835066bd6213fbeeec03704b4a1c206920b81c1ec2201d185f"},
|
||||
|
@ -71,14 +71,14 @@
|
|||
"guardian_db": {:hex, :guardian_db, "3.0.0", "c42902e3f1af1ba1e2d0c10913b926a1421f3a7e38eb4fc382b715c17489abdb", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.1", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:guardian, "~> 1.0 or ~> 2.0", [hex: :guardian, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "9c2ec4278efa34f9f1cc6ba795e552d41fdc7ffba5319d67eeb533b89392d183"},
|
||||
"guardian_phoenix": {:hex, :guardian_phoenix, "2.0.1", "89a817265af09a6ddf7cb1e77f17ffca90cea2db10ff888375ef34502b2731b1", [:mix], [{:guardian, "~> 2.0", [hex: :guardian, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "21f439246715192b231f228680465d1ed5fbdf01555a4a3b17165532f5f9a08c"},
|
||||
"hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
|
||||
"hammer": {:hex, :hammer, "6.1.0", "f263e3c3e9946bd410ea0336b2abe0cb6260af4afb3a221e1027540706e76c55", [:make, :mix], [{:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "b47e415a562a6d072392deabcd58090d8a41182cf9044cdd6b0d0faaaf68ba57"},
|
||||
"hammer": {:hex, :hammer, "6.2.0", "956e578f210ee67f7801caf7109b0e1145d2dad77ed5a0e5c0041a04739ede36", [:mix], [{:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "1431a30e1f9c816e0fc58d2587de2d5f4c709b74bf81be77515dc902e35bb3a7"},
|
||||
"haversine": {:hex, :haversine, "0.1.0", "14240e90dae07c9459f538d12a811492f655d95fc68f999403503b4f6c4ec522", [:mix], [], "hexpm", "54dc48e895bc18a59437a37026c873634e17b648a64cb87bfafb96f64d607060"},
|
||||
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
|
||||
"http_signatures": {:hex, :http_signatures, "0.1.2", "ed1cc7043abcf5bb4f30d68fb7bad9d618ec1a45c4ff6c023664e78b67d9c406", [:mix], [], "hexpm", "f08aa9ac121829dae109d608d83c84b940ef2f183ae50f2dd1e9a8bc619d8be7"},
|
||||
"httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"},
|
||||
"icalendar": {:git, "https://github.com/tcitworld/icalendar.git", "1033d922c82a7223db0ec138e2316557b70ff49f", []},
|
||||
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
||||
"inet_cidr": {:hex, :inet_cidr, "1.0.4", "a05744ab7c221ca8e395c926c3919a821eb512e8f36547c062f62c4ca0cf3d6e", [:mix], [], "hexpm", "64a2d30189704ae41ca7dbdd587f5291db5d1dda1414e0774c29ffc81088c1bc"},
|
||||
"inet_cidr": {:hex, :inet_cidr, "1.0.8", "d26bb7bdbdf21ae401ead2092bf2bb4bf57fe44a62f5eaa5025280720ace8a40", [:mix], [], "hexpm", "d5b26da66603bb56c933c65214c72152f0de9a6ea53618b56d63302a68f6a90e"},
|
||||
"ip_reserved": {:hex, :ip_reserved, "0.1.1", "e5112d71f1abf05207f82fd9597d369a5fde1e0b6d1bbe77c02a99bb26ecdc33", [:mix], [{:inet_cidr, "~> 1.0.0", [hex: :inet_cidr, repo: "hexpm", optional: false]}], "hexpm", "55fcd2b6e211caef09ea3f54ef37d43030bec486325d12fe865ab5ed8140a4fe"},
|
||||
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
|
||||
"jose": {:hex, :jose, "1.11.6", "613fda82552128aa6fb804682e3a616f4bc15565a048dabd05b1ebd5827ed965", [:mix, :rebar3], [], "hexpm", "6275cb75504f9c1e60eeacb771adfeee4905a9e182103aa59b53fed651ff9738"},
|
||||
|
@ -87,7 +87,7 @@
|
|||
"linkify": {:hex, :linkify, "0.5.3", "5f8143d8f61f5ff08d3aeeff47ef6509492b4948d8f08007fbf66e4d2246a7f2", [:mix], [], "hexpm", "3ef35a1377d47c25506e07c1c005ea9d38d700699d92ee92825f024434258177"},
|
||||
"makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "0.1.3", "d684f4bac8690e70b06eb52dad65d26de2eefa44cd19d64a8095e1417df7c8fd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "b78dc853d2e670ff6390b605d807263bf606da3c82be37f9d7f68635bd886fc9"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "0.1.4", "29563475afa9b8a2add1b7a9c8fb68d06ca7737648f28398e04461f008b69521", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f4ed47ecda66de70dd817698a703f8816daa91272e7e45812469498614ae8b29"},
|
||||
"meck": {:hex, :meck, "0.9.2", "85ccbab053f1db86c7ca240e9fc718170ee5bda03810a6292b5306bf31bae5f5", [:rebar3], [], "hexpm", "81344f561357dc40a8344afa53767c32669153355b626ea9fcbc8da6b3045826"},
|
||||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
||||
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
|
||||
|
@ -103,20 +103,20 @@
|
|||
"nimble_pool": {:hex, :nimble_pool, "0.2.6", "91f2f4c357da4c4a0a548286c84a3a28004f68f05609b4534526871a22053cde", [:mix], [], "hexpm", "1c715055095d3f2705c4e236c18b618420a35490da94149ff8b580a2144f653f"},
|
||||
"oauth2": {:hex, :oauth2, "2.1.0", "beb657f393814a3a7a8a15bd5e5776ecae341fd344df425342a3b6f1904c2989", [:mix], [{:tesla, "~> 1.5", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "8ac07f85b3307dd1acfeb0ec852f64161b22f57d0ce0c15e616a1dfc8ebe2b41"},
|
||||
"oauther": {:hex, :oauther, "1.3.0", "82b399607f0ca9d01c640438b34d74ebd9e4acd716508f868e864537ecdb1f76", [:mix], [], "hexpm", "78eb888ea875c72ca27b0864a6f550bc6ee84f2eeca37b093d3d833fbcaec04e"},
|
||||
"oban": {:hex, :oban, "2.17.1", "42d6221a1c17b63d81c19e3bad9ea82b59e39c47c1f9b7670ee33628569a449b", [:mix], [{:ecto_sql, "~> 3.6", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c02686ada7979b00e259c0efbafeae2749f8209747b3460001fe695c5bdbeee6"},
|
||||
"oban": {:hex, :oban, "2.17.3", "ddfd5710aadcd550d2e174c8d73ce5f1865601418cf54a91775f20443fb832b7", [:mix], [{:ecto_sql, "~> 3.6", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "452eada8bfe0d0fefd0740ab5fa8cf3ef6c375df0b4a3c3805d179022a04738a"},
|
||||
"paasaa": {:hex, :paasaa, "0.6.0", "07c8ed81010caa25db351d474f0c053072c809821c60f9646f7b1547bec52f6d", [:mix], [], "hexpm", "732ddfc21bac0831edb26aec468af3ec2b8997d74f6209810b1cc53199c29f2e"},
|
||||
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
|
||||
"phoenix": {:hex, :phoenix, "1.7.10", "02189140a61b2ce85bb633a9b6fd02dff705a5f1596869547aeb2b2b95edd729", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "cf784932e010fd736d656d7fead6a584a4498efefe5b8227e9f383bf15bb79d0"},
|
||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.4.3", "86e9878f833829c3f66da03d75254c155d91d72a201eb56ae83482328dc7ca93", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "d36c401206f3011fefd63d04e8ef626ec8791975d9d107f9a0817d426f61ac07"},
|
||||
"phoenix_html": {:hex, :phoenix_html, "3.3.3", "380b8fb45912b5638d2f1d925a3771b4516b9a78587249cabe394e0a5d579dc9", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "923ebe6fec6e2e3b3e569dfbdc6560de932cd54b000ada0208b5f45024bdd76c"},
|
||||
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.4.1", "2aff698f5e47369decde4357ba91fc9c37c6487a512b41732818f2204a8ef1d3", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "9bffb834e7ddf08467fe54ae58b5785507aaba6255568ae22b4d46e2bb3615ab"},
|
||||
"phoenix_live_view": {:hex, :phoenix_live_view, "0.20.3", "8b6406bc0a451f295407d7acff7f234a6314be5bbe0b3f90ed82b07f50049878", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a8e4385e05618b424779f894ed2df97d3c7518b7285fcd11979077ae6226466b"},
|
||||
"phoenix_live_view": {:hex, :phoenix_live_view, "0.20.4", "0dc21e89dbf5b1f3a69090a92d1a2724bfa951d5cbccff6c5b318e12eac107e3", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d8930c9c79dd25775646874abdf3d8d24356b88d58fa14f637c8e3418d36bce3"},
|
||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
|
||||
"phoenix_swoosh": {:hex, :phoenix_swoosh, "1.2.0", "a544d83fde4a767efb78f45404a74c9e37b2a9c5ea3339692e65a6966731f935", [:mix], [{:finch, "~> 0.8", [hex: :finch, repo: "hexpm", optional: true]}, {:hackney, "~> 1.10", [hex: :hackney, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.5", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "e88d117251e89a16b92222415a6d87b99a96747ddf674fc5c7631de734811dba"},
|
||||
"phoenix_swoosh": {:hex, :phoenix_swoosh, "1.2.1", "b74ccaa8046fbc388a62134360ee7d9742d5a8ae74063f34eb050279de7a99e1", [:mix], [{:finch, "~> 0.8", [hex: :finch, repo: "hexpm", optional: true]}, {:hackney, "~> 1.10", [hex: :hackney, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.5", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "4000eeba3f9d7d1a6bf56d2bd56733d5cadf41a7f0d8ffe5bb67e7d667e204a2"},
|
||||
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
|
||||
"phoenix_view": {:hex, :phoenix_view, "2.0.3", "4d32c4817fce933693741deeb99ef1392619f942633dde834a5163124813aad3", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "cd34049af41be2c627df99cd4eaa71fc52a328c0c3d8e7d4aa28f880c30e7f64"},
|
||||
"plug": {:hex, :plug, "1.15.2", "94cf1fa375526f30ff8770837cb804798e0045fd97185f0bb9e5fcd858c792a3", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "02731fa0c2dcb03d8d21a1d941bdbbe99c2946c0db098eee31008e04c6283615"},
|
||||
"plug_cowboy": {:hex, :plug_cowboy, "2.6.1", "9a3bbfceeb65eff5f39dab529e5cd79137ac36e913c02067dba3963a26efe9b2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "de36e1a21f451a18b790f37765db198075c25875c64834bcc82d90b309eb6613"},
|
||||
"plug": {:hex, :plug, "1.15.3", "712976f504418f6dff0a3e554c40d705a9bcf89a7ccef92fc6a5ef8f16a30a97", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cc4365a3c010a56af402e0809208873d113e9c38c401cabd88027ef4f5c01fd2"},
|
||||
"plug_cowboy": {:hex, :plug_cowboy, "2.6.2", "753611b23b29231fb916b0cdd96028084b12aff57bfd7b71781bd04b1dbeb5c9", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "951ed2433df22f4c97b85fdb145d4cee561f36b74854d64c06d896d7cd2921a7"},
|
||||
"plug_crypto": {:hex, :plug_crypto, "2.0.0", "77515cc10af06645abbfb5e6ad7a3e9714f805ae118fa1a70205f80d2d70fe73", [:mix], [], "hexpm", "53695bae57cc4e54566d993eb01074e4d894b65a3766f1c43e2c61a1b0f45ea9"},
|
||||
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
|
||||
"postgrex": {:hex, :postgrex, "0.17.4", "5777781f80f53b7c431a001c8dad83ee167bcebcf3a793e3906efff680ab62b3", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "6458f7d5b70652bc81c3ea759f91736c16a31be000f306d3c64bcdfe9a18b3cc"},
|
||||
|
@ -127,7 +127,7 @@
|
|||
"replug": {:hex, :replug, "0.1.0", "61d35f8c873c0078a23c49579a48f36e45789414b1ec0daee3fd5f4e34221f23", [:mix], [{:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "f71f7a57e944e854fe4946060c6964098e53958074c69fb844b96e0bd58cfa60"},
|
||||
"sentry": {:hex, :sentry, "8.1.0", "8d235b62fce5f8e067ea1644e30939405b71a5e1599d9529ff82899d11d03f2b", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 2.3", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "f9fc7641ef61e885510f5e5963c2948b9de1de597c63f781e9d3d6c9c8681ab4"},
|
||||
"shortuuid": {:hex, :shortuuid, "3.0.0", "028684d9eeed0ad4b800e8481afd854e1a61c526f35952455b2ee4248601e7b8", [:mix], [], "hexpm", "dfd8f80f514cbb91622cb83f4ac0d6e2f06d98cc6d4aeba94444a212289d0d39"},
|
||||
"sitemapper": {:hex, :sitemapper, "0.7.0", "4aee7930327a9a01b1c9b81d1d42f60c1a295e9f420108eb2d130c317415abd7", [:mix], [{:ex_aws_s3, "~> 2.0", [hex: :ex_aws_s3, repo: "hexpm", optional: true]}, {:xml_builder, "~> 2.1", [hex: :xml_builder, repo: "hexpm", optional: false]}], "hexpm", "60f7a684e5e9fe7f10ac5b69f48b0be2bcbba995afafcb3c143fc0c8ef1f223f"},
|
||||
"sitemapper": {:hex, :sitemapper, "0.8.0", "50c8c85ed38c013829ce700e8a8d195a2faf4aed8685659b14529dcb6f91fee0", [:mix], [{:ex_aws_s3, "~> 2.0", [hex: :ex_aws_s3, repo: "hexpm", optional: true]}, {:xml_builder, "~> 2.1", [hex: :xml_builder, repo: "hexpm", optional: false]}], "hexpm", "7cd42b454035da457151c9b6a314b688b5bbe5383add95badc65d013c25989c5"},
|
||||
"sleeplocks": {:hex, :sleeplocks, "1.1.2", "d45aa1c5513da48c888715e3381211c859af34bee9b8290490e10c90bb6ff0ca", [:rebar3], [], "hexpm", "9fe5d048c5b781d6305c1a3a0f40bb3dfc06f49bf40571f3d2d0c57eaa7f59a5"},
|
||||
"slugger": {:hex, :slugger, "0.3.0", "efc667ab99eee19a48913ccf3d038b1fb9f165fa4fbf093be898b8099e61b6ed", [:mix], [], "hexpm", "20d0ded0e712605d1eae6c5b4889581c3460d92623a930ddda91e0e609b5afba"},
|
||||
"slugify": {:hex, :slugify, "1.3.1", "0d3b8b7e5c1eeaa960e44dce94382bee34a39b3ea239293e457a9c5b47cc6fd3", [:mix], [], "hexpm", "cb090bbeb056b312da3125e681d98933a360a70d327820e4b7f91645c4d8be76"},
|
||||
|
@ -135,14 +135,14 @@
|
|||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
|
||||
"struct_access": {:hex, :struct_access, "1.1.2", "a42e6ceedd9b9ea090ee94a6da089d56e16f374dbbc010c3eebdf8be17df286f", [:mix], [], "hexpm", "e4c411dcc0226081b95709909551fc92b8feb1a3476108348ea7e3f6c12e586a"},
|
||||
"sweet_xml": {:hex, :sweet_xml, "0.7.4", "a8b7e1ce7ecd775c7e8a65d501bc2cd933bff3a9c41ab763f5105688ef485d08", [:mix], [], "hexpm", "e7c4b0bdbf460c928234951def54fe87edf1a170f6896675443279e2dbeba167"},
|
||||
"swoosh": {:hex, :swoosh, "1.14.3", "949e6bf6dd469449238a94ec6f19ec10b63fc8753de7f3ebe3d3aeaf772f4c6b", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.4 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6c565103fc8f086bdd96e5c948660af8e20922b7a90a75db261f06a34f805c8b"},
|
||||
"swoosh": {:hex, :swoosh, "1.15.2", "490ea85a98e8fb5178c07039e0d8519839e38127724a58947a668c00db7574ee", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.4 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9f7739c02f6c7c0ca82ee397f3bfe0465dbe4c8a65372ac2a5584bf147dd5831"},
|
||||
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
|
||||
"tesla": {:hex, :tesla, "1.8.0", "d511a4f5c5e42538d97eef7c40ec4f3e44effdc5068206f42ed859e09e51d1fd", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "10501f360cd926a309501287470372af1a6e1cbed0f43949203a4c13300bc79f"},
|
||||
"timex": {:hex, :timex, "3.7.11", "bb95cb4eb1d06e27346325de506bcc6c30f9c6dea40d1ebe390b262fad1862d1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.20", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "8b9024f7efbabaf9bd7aa04f65cf8dcd7c9818ca5737677c7b76acbc6a94d1aa"},
|
||||
"tls_certificate_check": {:hex, :tls_certificate_check, "1.21.0", "042ab2c0c860652bc5cf69c94e3a31f96676d14682e22ec7813bd173ceff1788", [:rebar3], [{:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "6cee6cffc35a390840d48d463541d50746a7b0e421acaadb833cfc7961e490e7"},
|
||||
"tz_world": {:hex, :tz_world, "1.3.2", "15d331ad1ff22735dfcc8c98bfc7b2a9fdc17f1f071e31e21cdafe2d9318a300", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.5", [hex: :certifi, repo: "hexpm", optional: true]}, {:geo, "~> 1.0 or ~> 2.0 or ~> 3.3", [hex: :geo, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "d1a345e07b3378c4c902ad54fbd5d54c8c3dd55dba883b7407fe57bcec45ff2a"},
|
||||
"tzdata": {:hex, :tzdata, "1.1.1", "20c8043476dfda8504952d00adac41c6eda23912278add38edc140ae0c5bcc46", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a69cec8352eafcd2e198dea28a34113b60fdc6cb57eb5ad65c10292a6ba89787"},
|
||||
"ueberauth": {:hex, :ueberauth, "0.10.5", "806adb703df87e55b5615cf365e809f84c20c68aa8c08ff8a416a5a6644c4b02", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3efd1f31d490a125c7ed453b926f7c31d78b97b8a854c755f5c40064bf3ac9e1"},
|
||||
"ueberauth": {:hex, :ueberauth, "0.10.7", "5a31cbe11e7ce5c7484d745dc9e1f11948e89662f8510d03c616de03df581ebd", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "0bccf73e2ffd6337971340832947ba232877aa8122dba4c95be9f729c8987377"},
|
||||
"ueberauth_cas": {:hex, :ueberauth_cas, "2.3.1", "df45a1f2c5df8bc80191cbca4baeeed808d697702ec5ebe5bd5d5a264481752f", [:mix], [{:httpoison, "~> 1.8", [hex: :httpoison, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.6", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "5068ae2b9e217c2f05aa9a67483a6531e21ba0be9a6f6c8749bb7fd1599be321"},
|
||||
"ueberauth_discord": {:hex, :ueberauth_discord, "0.7.0", "463f6dfe1ed10a76739331ce8e1dd3600ab611f10524dd828eb3aa50e76e9d43", [:mix], [{:oauth2, "~> 1.0 or ~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.7", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "d6f98ef91abb4ddceada4b7acba470e0e68c4d2de9735ff2f24172a8e19896b4"},
|
||||
"ueberauth_facebook": {:hex, :ueberauth_facebook, "0.10.0", "0d607fbd1b7c6e0449981571027d869c2d156b8ad20c42e3672346678c05ccf1", [:mix], [{:oauth2, "~> 1.0 or ~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.7", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "bf8ce5d66b1c50da8abff77e8086c1b710bdde63f4acaef19a651ba43a9537a8"},
|
||||
|
|
74
mix.nix
74
mix.nix
|
@ -205,12 +205,12 @@ let
|
|||
|
||||
cowboy = buildErlangMk rec {
|
||||
name = "cowboy";
|
||||
version = "2.10.0";
|
||||
version = "2.11.0";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "cowboy";
|
||||
version = "${version}";
|
||||
sha256 = "3afdccb7183cc6f143cb14d3cf51fa00e53db9ec80cdcd525482f5e99bc41d6b";
|
||||
sha256 = "0fa395437f1b0e104e0e00999f39d2ac5f4082ac5049b67a5b6d56ecc31b1403";
|
||||
};
|
||||
|
||||
beamDeps = [ cowlib ranch ];
|
||||
|
@ -244,12 +244,12 @@ let
|
|||
|
||||
credo = buildMix rec {
|
||||
name = "credo";
|
||||
version = "1.7.2";
|
||||
version = "1.7.3";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "credo";
|
||||
version = "${version}";
|
||||
sha256 = "dd15d6fbc280f6cf9b269f41df4e4992dee6615939653b164ef951f60afcb68e";
|
||||
sha256 = "35ea675a094c934c22fb1dca3696f3c31f2728ae6ef5a53b5d648c11180a4535";
|
||||
};
|
||||
|
||||
beamDeps = [ bunt file_system jason ];
|
||||
|
@ -465,15 +465,15 @@ let
|
|||
|
||||
elixir_make = buildMix rec {
|
||||
name = "elixir_make";
|
||||
version = "0.7.7";
|
||||
version = "0.7.8";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "elixir_make";
|
||||
version = "${version}";
|
||||
sha256 = "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c";
|
||||
sha256 = "7a71945b913d37ea89b06966e1342c85cfe549b15e6d6d081e8081c493062c07";
|
||||
};
|
||||
|
||||
beamDeps = [ castore ];
|
||||
beamDeps = [ castore certifi ];
|
||||
};
|
||||
|
||||
erlex = buildMix rec {
|
||||
|
@ -582,12 +582,12 @@ let
|
|||
|
||||
ex_cldr_numbers = buildMix rec {
|
||||
name = "ex_cldr_numbers";
|
||||
version = "2.32.3";
|
||||
version = "2.32.4";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "ex_cldr_numbers";
|
||||
version = "${version}";
|
||||
sha256 = "7b626ff1e59a0ec9c3c5db5ce9ca91a6995e2ab56426b71f3cbf67181ea225f5";
|
||||
sha256 = "6fd5a82f0785418fa8b698c0be2b1845dff92b77f1b3172c763d37868fb503d2";
|
||||
};
|
||||
|
||||
beamDeps = [ decimal digital_token ex_cldr ex_cldr_currencies jason ];
|
||||
|
@ -608,12 +608,12 @@ let
|
|||
|
||||
ex_doc = buildMix rec {
|
||||
name = "ex_doc";
|
||||
version = "0.31.0";
|
||||
version = "0.31.1";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "ex_doc";
|
||||
version = "${version}";
|
||||
sha256 = "5350cafa6b7f77bdd107aa2199fe277acf29d739aba5aee7e865fc680c62a110";
|
||||
sha256 = "3178c3a407c557d8343479e1ff117a96fd31bafe52a039079593fb0524ef61b0";
|
||||
};
|
||||
|
||||
beamDeps = [ earmark_parser makeup_elixir makeup_erlang ];
|
||||
|
@ -725,12 +725,12 @@ let
|
|||
|
||||
fast_html = buildMix rec {
|
||||
name = "fast_html";
|
||||
version = "2.2.0";
|
||||
version = "2.3.0";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "fast_html";
|
||||
version = "${version}";
|
||||
sha256 = "064c4f23b4a6168f9187dac8984b056f2c531bb0787f559fd6a8b34b38aefbae";
|
||||
sha256 = "f18e3c7668f82d3ae0b15f48d48feeb257e28aa5ab1b0dbf781c7312e5da029d";
|
||||
};
|
||||
|
||||
beamDeps = [ elixir_make nimble_pool ];
|
||||
|
@ -777,12 +777,12 @@ let
|
|||
|
||||
floki = buildMix rec {
|
||||
name = "floki";
|
||||
version = "0.35.2";
|
||||
version = "0.35.3";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "floki";
|
||||
version = "${version}";
|
||||
sha256 = "6b05289a8e9eac475f644f09c2e4ba7e19201fd002b89c28c1293e7bd16773d9";
|
||||
sha256 = "6d9f07f3fc76599f3b66c39f4a81ac62c8f4d9631140268db92aacad5d0e56d4";
|
||||
};
|
||||
|
||||
beamDeps = [];
|
||||
|
@ -933,12 +933,12 @@ let
|
|||
|
||||
hammer = buildMix rec {
|
||||
name = "hammer";
|
||||
version = "6.1.0";
|
||||
version = "6.2.0";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "hammer";
|
||||
version = "${version}";
|
||||
sha256 = "b47e415a562a6d072392deabcd58090d8a41182cf9044cdd6b0d0faaaf68ba57";
|
||||
sha256 = "1431a30e1f9c816e0fc58d2587de2d5f4c709b74bf81be77515dc902e35bb3a7";
|
||||
};
|
||||
|
||||
beamDeps = [ poolboy ];
|
||||
|
@ -1011,12 +1011,12 @@ let
|
|||
|
||||
inet_cidr = buildMix rec {
|
||||
name = "inet_cidr";
|
||||
version = "1.0.4";
|
||||
version = "1.0.8";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "inet_cidr";
|
||||
version = "${version}";
|
||||
sha256 = "64a2d30189704ae41ca7dbdd587f5291db5d1dda1414e0774c29ffc81088c1bc";
|
||||
sha256 = "d5b26da66603bb56c933c65214c72152f0de9a6ea53618b56d63302a68f6a90e";
|
||||
};
|
||||
|
||||
beamDeps = [];
|
||||
|
@ -1128,12 +1128,12 @@ let
|
|||
|
||||
makeup_erlang = buildMix rec {
|
||||
name = "makeup_erlang";
|
||||
version = "0.1.3";
|
||||
version = "0.1.4";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "makeup_erlang";
|
||||
version = "${version}";
|
||||
sha256 = "b78dc853d2e670ff6390b605d807263bf606da3c82be37f9d7f68635bd886fc9";
|
||||
sha256 = "f4ed47ecda66de70dd817698a703f8816daa91272e7e45812469498614ae8b29";
|
||||
};
|
||||
|
||||
beamDeps = [ makeup ];
|
||||
|
@ -1336,12 +1336,12 @@ let
|
|||
|
||||
oban = buildMix rec {
|
||||
name = "oban";
|
||||
version = "2.17.1";
|
||||
version = "2.17.3";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "oban";
|
||||
version = "${version}";
|
||||
sha256 = "c02686ada7979b00e259c0efbafeae2749f8209747b3460001fe695c5bdbeee6";
|
||||
sha256 = "452eada8bfe0d0fefd0740ab5fa8cf3ef6c375df0b4a3c3805d179022a04738a";
|
||||
};
|
||||
|
||||
beamDeps = [ ecto_sql jason postgrex telemetry ];
|
||||
|
@ -1427,12 +1427,12 @@ let
|
|||
|
||||
phoenix_live_view = buildMix rec {
|
||||
name = "phoenix_live_view";
|
||||
version = "0.20.3";
|
||||
version = "0.20.4";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "phoenix_live_view";
|
||||
version = "${version}";
|
||||
sha256 = "a8e4385e05618b424779f894ed2df97d3c7518b7285fcd11979077ae6226466b";
|
||||
sha256 = "d8930c9c79dd25775646874abdf3d8d24356b88d58fa14f637c8e3418d36bce3";
|
||||
};
|
||||
|
||||
beamDeps = [ jason phoenix phoenix_html phoenix_template phoenix_view plug telemetry ];
|
||||
|
@ -1453,12 +1453,12 @@ let
|
|||
|
||||
phoenix_swoosh = buildMix rec {
|
||||
name = "phoenix_swoosh";
|
||||
version = "1.2.0";
|
||||
version = "1.2.1";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "phoenix_swoosh";
|
||||
version = "${version}";
|
||||
sha256 = "e88d117251e89a16b92222415a6d87b99a96747ddf674fc5c7631de734811dba";
|
||||
sha256 = "4000eeba3f9d7d1a6bf56d2bd56733d5cadf41a7f0d8ffe5bb67e7d667e204a2";
|
||||
};
|
||||
|
||||
beamDeps = [ hackney phoenix phoenix_html phoenix_view swoosh ];
|
||||
|
@ -1492,12 +1492,12 @@ let
|
|||
|
||||
plug = buildMix rec {
|
||||
name = "plug";
|
||||
version = "1.15.2";
|
||||
version = "1.15.3";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "plug";
|
||||
version = "${version}";
|
||||
sha256 = "02731fa0c2dcb03d8d21a1d941bdbbe99c2946c0db098eee31008e04c6283615";
|
||||
sha256 = "cc4365a3c010a56af402e0809208873d113e9c38c401cabd88027ef4f5c01fd2";
|
||||
};
|
||||
|
||||
beamDeps = [ mime plug_crypto telemetry ];
|
||||
|
@ -1505,12 +1505,12 @@ let
|
|||
|
||||
plug_cowboy = buildMix rec {
|
||||
name = "plug_cowboy";
|
||||
version = "2.6.1";
|
||||
version = "2.6.2";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "plug_cowboy";
|
||||
version = "${version}";
|
||||
sha256 = "de36e1a21f451a18b790f37765db198075c25875c64834bcc82d90b309eb6613";
|
||||
sha256 = "951ed2433df22f4c97b85fdb145d4cee561f36b74854d64c06d896d7cd2921a7";
|
||||
};
|
||||
|
||||
beamDeps = [ cowboy cowboy_telemetry plug ];
|
||||
|
@ -1635,12 +1635,12 @@ let
|
|||
|
||||
sitemapper = buildMix rec {
|
||||
name = "sitemapper";
|
||||
version = "0.7.0";
|
||||
version = "0.8.0";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "sitemapper";
|
||||
version = "${version}";
|
||||
sha256 = "60f7a684e5e9fe7f10ac5b69f48b0be2bcbba995afafcb3c143fc0c8ef1f223f";
|
||||
sha256 = "7cd42b454035da457151c9b6a314b688b5bbe5383add95badc65d013c25989c5";
|
||||
};
|
||||
|
||||
beamDeps = [ xml_builder ];
|
||||
|
@ -1739,12 +1739,12 @@ let
|
|||
|
||||
swoosh = buildMix rec {
|
||||
name = "swoosh";
|
||||
version = "1.14.3";
|
||||
version = "1.15.2";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "swoosh";
|
||||
version = "${version}";
|
||||
sha256 = "6c565103fc8f086bdd96e5c948660af8e20922b7a90a75db261f06a34f805c8b";
|
||||
sha256 = "9f7739c02f6c7c0ca82ee397f3bfe0465dbe4c8a65372ac2a5584bf147dd5831";
|
||||
};
|
||||
|
||||
beamDeps = [ cowboy gen_smtp hackney jason mime plug plug_cowboy telemetry ];
|
||||
|
@ -1830,12 +1830,12 @@ let
|
|||
|
||||
ueberauth = buildMix rec {
|
||||
name = "ueberauth";
|
||||
version = "0.10.5";
|
||||
version = "0.10.7";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "ueberauth";
|
||||
version = "${version}";
|
||||
sha256 = "3efd1f31d490a125c7ed453b926f7c31d78b97b8a854c755f5c40064bf3ac9e1";
|
||||
sha256 = "0bccf73e2ffd6337971340832947ba232877aa8122dba4c95be9f729c8987377";
|
||||
};
|
||||
|
||||
beamDeps = [ plug ];
|
||||
|
|
2808
package-lock.json
generated
2808
package-lock.json
generated
File diff suppressed because it is too large
Load diff
23
package.json
23
package.json
|
@ -15,7 +15,8 @@
|
|||
"story:preview": "histoire preview",
|
||||
"test": "vitest",
|
||||
"coverage": "vitest run --coverage",
|
||||
"pre-commit": "lint-staged"
|
||||
"pre-commit": "lint-staged",
|
||||
"postinstall": "patch-package"
|
||||
},
|
||||
"lint-staged": {
|
||||
"**/*.{js,ts,vue}": [
|
||||
|
@ -27,6 +28,7 @@
|
|||
"mix credo"
|
||||
]
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.3.16",
|
||||
"@framasoft/socket": "^1.0.0",
|
||||
|
@ -77,7 +79,7 @@
|
|||
"blurhash": "^2.0.0",
|
||||
"date-fns": "^2.16.0",
|
||||
"date-fns-tz": "^2.0.0",
|
||||
"floating-vue": "^2.0.0-beta.24",
|
||||
"floating-vue": "^5.0.0",
|
||||
"graphql": "^16.8.1",
|
||||
"graphql-tag": "^2.10.3",
|
||||
"hammerjs": "^2.0.8",
|
||||
|
@ -90,6 +92,7 @@
|
|||
"lodash": "^4.17.11",
|
||||
"ngeohash": "^0.6.3",
|
||||
"p-debounce": "^4.0.0",
|
||||
"patch-package": "^8.0.0",
|
||||
"phoenix": "^1.6",
|
||||
"postcss": "^8",
|
||||
"register-service-worker": "^1.7.2",
|
||||
|
@ -97,7 +100,7 @@
|
|||
"tailwindcss": "^3",
|
||||
"tippy.js": "^6.2.3",
|
||||
"unfetch": "^5.0.0",
|
||||
"vue": "^3.2.37",
|
||||
"vue": "3.4.16",
|
||||
"vue-i18n": "9",
|
||||
"vue-material-design-icons": "^5.1.2",
|
||||
"vue-matomo": "^4.1.0",
|
||||
|
@ -121,9 +124,9 @@
|
|||
"@types/ngeohash": "^0.6.2",
|
||||
"@types/phoenix": "^1.5.2",
|
||||
"@types/sanitize-html": "^2.5.0",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"@vitest/coverage-v8": "^0.34.1",
|
||||
"@vitest/ui": "^0.34.1",
|
||||
"@vitejs/plugin-vue": "^5.0.0",
|
||||
"@vitest/coverage-v8": "^1.2.2",
|
||||
"@vitest/ui": "^1.2.2",
|
||||
"@vue/eslint-config-prettier": "^9.0.0",
|
||||
"@vue/eslint-config-typescript": "^12.0.0",
|
||||
"@vue/test-utils": "^2.0.2",
|
||||
|
@ -134,8 +137,8 @@
|
|||
"eslint-plugin-vue": "^9.3.0",
|
||||
"flush-promises": "^1.0.2",
|
||||
"histoire": "^0.17.0",
|
||||
"husky": "^8.0.3",
|
||||
"jsdom": "^22.0.0",
|
||||
"husky": "^9.0.10",
|
||||
"jsdom": "^24.0.0",
|
||||
"lint-staged": "^15.1.0",
|
||||
"mock-apollo-client": "^1.1.0",
|
||||
"prettier": "^3.0.0",
|
||||
|
@ -143,10 +146,10 @@
|
|||
"rollup-plugin-visualizer": "^5.7.1",
|
||||
"sass": "^1.34.1",
|
||||
"typescript": "~5.3.2",
|
||||
"vite": "^4.5.0",
|
||||
"vite": "^5.0.12",
|
||||
"vite-plugin-pwa": "^0.17.0",
|
||||
"vite-svg-loader": "^4.0.0",
|
||||
"vitest": "^0.34.1",
|
||||
"vitest": "^1.2.2",
|
||||
"vue-i18n-extract": "^2.0.4",
|
||||
"vue-router-mock": "^1.0.0"
|
||||
}
|
||||
|
|
66
patches/vue-i18n-extract+2.0.7.patch
Normal file
66
patches/vue-i18n-extract+2.0.7.patch
Normal file
|
@ -0,0 +1,66 @@
|
|||
diff --git a/node_modules/vue-i18n-extract/dist/vue-i18n-extract.modern.mjs b/node_modules/vue-i18n-extract/dist/vue-i18n-extract.modern.mjs
|
||||
index 670733e..872d1af 100644
|
||||
--- a/node_modules/vue-i18n-extract/dist/vue-i18n-extract.modern.mjs
|
||||
+++ b/node_modules/vue-i18n-extract/dist/vue-i18n-extract.modern.mjs
|
||||
@@ -38,7 +38,7 @@ var defaultConfig = {
|
||||
};
|
||||
|
||||
function initCommand() {
|
||||
- fs.writeFileSync(path.resolve(process.cwd(), './vue-i18n-extract.config.js'), `module.exports = ${JSON.stringify(defaultConfig, null, 2)}`);
|
||||
+ fs.writeFileSync(path.resolve(process.cwd(), './vue-i18n-extract.config.cjs'), `module.exports = ${JSON.stringify(defaultConfig, null, 2)}`);
|
||||
}
|
||||
function resolveConfig() {
|
||||
const argvOptions = cac().parse(process.argv, {
|
||||
@@ -47,7 +47,7 @@ function resolveConfig() {
|
||||
let options;
|
||||
|
||||
try {
|
||||
- const pathToConfigFile = path.resolve(process.cwd(), './vue-i18n-extract.config.js'); // eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
+ const pathToConfigFile = path.resolve(process.cwd(), './vue-i18n-extract.config.cjs'); // eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
|
||||
const configOptions = require(pathToConfigFile);
|
||||
|
||||
diff --git a/node_modules/vue-i18n-extract/dist/vue-i18n-extract.umd.js b/node_modules/vue-i18n-extract/dist/vue-i18n-extract.umd.js
|
||||
index ca19c7a..11cb846 100644
|
||||
--- a/node_modules/vue-i18n-extract/dist/vue-i18n-extract.umd.js
|
||||
+++ b/node_modules/vue-i18n-extract/dist/vue-i18n-extract.umd.js
|
||||
@@ -45,7 +45,7 @@
|
||||
};
|
||||
|
||||
function initCommand() {
|
||||
- fs__default["default"].writeFileSync(path__default["default"].resolve(process.cwd(), './vue-i18n-extract.config.js'), `module.exports = ${JSON.stringify(defaultConfig, null, 2)}`);
|
||||
+ fs__default["default"].writeFileSync(path__default["default"].resolve(process.cwd(), './vue-i18n-extract.config.cjs'), `module.exports = ${JSON.stringify(defaultConfig, null, 2)}`);
|
||||
}
|
||||
function resolveConfig() {
|
||||
const argvOptions = cac__default["default"]().parse(process.argv, {
|
||||
@@ -54,7 +54,7 @@
|
||||
let options;
|
||||
|
||||
try {
|
||||
- const pathToConfigFile = path__default["default"].resolve(process.cwd(), './vue-i18n-extract.config.js'); // eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
+ const pathToConfigFile = path__default["default"].resolve(process.cwd(), './vue-i18n-extract.config.cjs'); // eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
|
||||
const configOptions = require(pathToConfigFile);
|
||||
|
||||
diff --git a/node_modules/vue-i18n-extract/src/config-file/index.ts b/node_modules/vue-i18n-extract/src/config-file/index.ts
|
||||
index 3db836f..744bd74 100644
|
||||
--- a/node_modules/vue-i18n-extract/src/config-file/index.ts
|
||||
+++ b/node_modules/vue-i18n-extract/src/config-file/index.ts
|
||||
@@ -5,7 +5,7 @@ import defaultConfig from './vue-i18n-extract.config';
|
||||
|
||||
export function initCommand(): void {
|
||||
fs.writeFileSync(
|
||||
- path.resolve(process.cwd(), './vue-i18n-extract.config.js'),
|
||||
+ path.resolve(process.cwd(), './vue-i18n-extract.config.cjs'),
|
||||
`module.exports = ${JSON.stringify(defaultConfig, null, 2)}`,
|
||||
);
|
||||
}
|
||||
@@ -16,7 +16,7 @@ export function resolveConfig (): Record<string, string> {
|
||||
let options;
|
||||
|
||||
try {
|
||||
- const pathToConfigFile = path.resolve(process.cwd(), './vue-i18n-extract.config.js');
|
||||
+ const pathToConfigFile = path.resolve(process.cwd(), './vue-i18n-extract.config.cjs');
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const configOptions = require(pathToConfigFile);
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
module.exports = {
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
|
|
|
@ -146,22 +146,37 @@ body {
|
|||
.taginput-item {
|
||||
@apply bg-primary mr-2;
|
||||
}
|
||||
.taginput-autocomplete {
|
||||
@apply flex-1 !drop-shadow-none;
|
||||
}
|
||||
.taginput-expanded {
|
||||
@apply w-full;
|
||||
}
|
||||
.taginput .autocomplete .dropdown-menu {
|
||||
@apply w-full;
|
||||
}
|
||||
.taginput-container {
|
||||
@apply border-none;
|
||||
}
|
||||
|
||||
.taginput-item:first-child {
|
||||
@apply ml-2;
|
||||
}
|
||||
.taginput-input-wrapper {
|
||||
@apply block;
|
||||
}
|
||||
|
||||
/* Autocomplete */
|
||||
.autocomplete {
|
||||
@apply max-h-[200px] drop-shadow-md text-black z-10;
|
||||
}
|
||||
|
||||
.autocomplete-item {
|
||||
@apply py-1.5 px-4 text-start;
|
||||
.autocomplete .autocomplete-item {
|
||||
@apply text-start p-2;
|
||||
}
|
||||
|
||||
.autocomplete-item-group-title {
|
||||
@apply opacity-50 py-0 px-2;
|
||||
.autocomplete .autocomplete-item-group-title {
|
||||
@apply opacity-50 py-1.5 px-2 dark:text-white dark:opacity-75;
|
||||
}
|
||||
|
||||
/* Dropdown */
|
||||
|
@ -173,7 +188,7 @@ body {
|
|||
@apply bg-white dark:bg-zinc-700 shadow-lg rounded text-start py-2;
|
||||
}
|
||||
.dropdown-item {
|
||||
@apply relative inline-flex gap-1 no-underline p-2 cursor-pointer w-full;
|
||||
@apply relative inline-flex gap-1 no-underline p-2 cursor-pointer w-full hover:bg-[#f5f5f5] hover:text-black;
|
||||
}
|
||||
|
||||
.dropdown-item-active {
|
||||
|
@ -343,8 +358,8 @@ button.menubar__button {
|
|||
.o-drop__menu--active {
|
||||
@apply z-50;
|
||||
}
|
||||
.o-dpck__box {
|
||||
@apply px-4 py-1;
|
||||
.datepicker-box {
|
||||
@apply block px-4 py-1 hover:bg-transparent;
|
||||
}
|
||||
.o-dpck__header {
|
||||
@apply pb-2 mb-2;
|
||||
|
@ -352,7 +367,7 @@ button.menubar__button {
|
|||
}
|
||||
.o-dpck__header__next,
|
||||
.o-dpck__header__previous {
|
||||
@apply justify-center text-center no-underline cursor-pointer items-center shadow-none inline-flex relative select-none leading-6 border rounded h-10 p-2 m-1 dark:text-white;
|
||||
@apply justify-center text-center no-underline cursor-pointer items-center shadow-none inline-flex relative select-none leading-6 border rounded h-10 p-2 m-1 dark:text-white hover:px-2;
|
||||
min-width: 2.25em;
|
||||
}
|
||||
.o-dpck__header__list {
|
||||
|
|
|
@ -30,7 +30,9 @@
|
|||
class="flex-1 min-w-[200px]"
|
||||
>
|
||||
<template v-slot="props">
|
||||
<div class="dark:bg-violet-3 p-1 flex items-center gap-1">
|
||||
<div
|
||||
class="dark:bg-violet-3 p-1 flex items-center gap-1 flex-1 dark:text-white"
|
||||
>
|
||||
<div class="">
|
||||
<img
|
||||
v-if="
|
||||
|
@ -41,6 +43,7 @@
|
|||
width="24"
|
||||
height="24"
|
||||
alt=""
|
||||
class="dark:fill-white"
|
||||
/>
|
||||
<o-icon v-else-if="props.option.icon" :icon="props.option.icon" />
|
||||
<o-icon v-else icon="help-circle" />
|
||||
|
|
|
@ -44,7 +44,9 @@
|
|||
<o-icon :icon="addressToPoiInfos(option).poiIcon.icon" />
|
||||
<b>{{ addressToPoiInfos(option).name }}</b>
|
||||
</p>
|
||||
<small>{{ addressToPoiInfos(option).alternativeName }}</small>
|
||||
<p class="text-small">
|
||||
{{ addressToPoiInfos(option).alternativeName }}
|
||||
</p>
|
||||
</template>
|
||||
<template #empty>
|
||||
<template v-if="isFetching">{{ t("Searching…") }}</template>
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
<template>
|
||||
<o-field :label-for="id">
|
||||
<o-field :label-for="id" class="taginput-field">
|
||||
<template #label>
|
||||
{{ $t("Add some tags") }}
|
||||
<o-tooltip
|
||||
variant="dark"
|
||||
:label="
|
||||
$t('You can add tags by hitting the Enter key or by adding a comma')
|
||||
"
|
||||
>
|
||||
<HelpCircleOutline :size="16" />
|
||||
</o-tooltip>
|
||||
<p class="inline-flex items-center gap-0.5">
|
||||
{{ t("Add some tags") }}
|
||||
<o-tooltip
|
||||
variant="dark"
|
||||
:label="
|
||||
t('You can add tags by hitting the Enter key or by adding a comma')
|
||||
"
|
||||
>
|
||||
<HelpCircleOutline :size="16" />
|
||||
</o-tooltip>
|
||||
</p>
|
||||
</template>
|
||||
<o-taginput
|
||||
v-model="tagsStrings"
|
||||
|
@ -20,10 +22,11 @@
|
|||
icon="label"
|
||||
:maxlength="20"
|
||||
:maxitems="10"
|
||||
:placeholder="$t('Eg: Stockholm, Dance, Chess…')"
|
||||
@input="debouncedGetFilteredTags"
|
||||
:placeholder="t('Eg: Stockholm, Dance, Chess…')"
|
||||
@input="getFilteredTags"
|
||||
:id="id"
|
||||
dir="auto"
|
||||
expanded
|
||||
>
|
||||
</o-taginput>
|
||||
</o-field>
|
||||
|
@ -31,11 +34,11 @@
|
|||
<script lang="ts" setup>
|
||||
import differenceBy from "lodash/differenceBy";
|
||||
import { ITag } from "../../types/tag.model";
|
||||
import debounce from "lodash/debounce";
|
||||
import { computed, onBeforeMount, ref } from "vue";
|
||||
import HelpCircleOutline from "vue-material-design-icons/HelpCircleOutline.vue";
|
||||
import { useFetchTags } from "@/composition/apollo/tags";
|
||||
import { FILTER_TAGS } from "@/graphql/tags";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: ITag[];
|
||||
|
@ -47,6 +50,8 @@ const text = ref("");
|
|||
|
||||
const tags = ref<ITag[]>([]);
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
let componentId = 0;
|
||||
|
||||
onBeforeMount(() => {
|
||||
|
@ -61,14 +66,16 @@ const { load: fetchTags } = useFetchTags();
|
|||
|
||||
const getFilteredTags = async (newText: string): Promise<void> => {
|
||||
text.value = newText;
|
||||
const res = await fetchTags(FILTER_TAGS, { filter: newText });
|
||||
const res = await fetchTags(
|
||||
FILTER_TAGS,
|
||||
{ filter: newText },
|
||||
{ debounce: 200 }
|
||||
);
|
||||
if (res) {
|
||||
tags.value = res.tags;
|
||||
}
|
||||
};
|
||||
|
||||
const debouncedGetFilteredTags = debounce(getFilteredTags, 200);
|
||||
|
||||
const filteredTags = computed((): ITag[] => {
|
||||
return differenceBy(tags.value, props.modelValue, "id").filter(
|
||||
(option) =>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
v-if="currentActor"
|
||||
:currentActor="currentActor"
|
||||
:placeholder="t('Write a new message')"
|
||||
:required="true"
|
||||
/>
|
||||
<o-notification
|
||||
class="my-2"
|
||||
|
@ -133,6 +134,7 @@ const sendForm = (e: Event) => {
|
|||
e.preventDefault();
|
||||
console.debug("Sending new private message");
|
||||
if (!currentActor.value?.id || !event.value.id) return;
|
||||
errors.value = [];
|
||||
eventPrivateMessageMutate({
|
||||
text: text.value,
|
||||
actorId:
|
||||
|
@ -150,7 +152,10 @@ onEventPrivateMessageMutated(() => {
|
|||
|
||||
onEventPrivateMessageError((err) => {
|
||||
err.graphQLErrors.forEach((error) => {
|
||||
errors.value.push(error.message);
|
||||
const message = Array.isArray(error.message)
|
||||
? error.message
|
||||
: [error.message];
|
||||
errors.value.push(...message);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<section>
|
||||
<div
|
||||
class="flex gap-1 flex-row mb-3 bg-mbz-yellow p-3 rounded items-center"
|
||||
class="flex gap-1 flex-row mb-3 bg-mbz-yellow dark:text-black p-3 rounded items-center"
|
||||
>
|
||||
<o-icon
|
||||
icon="alert"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<span
|
||||
class="rounded-md truncate text-sm text-violet-title px-2 py-1"
|
||||
class="rounded-md truncate text-sm text-black px-2 py-1"
|
||||
:class="[
|
||||
typeClasses,
|
||||
capitalize,
|
||||
|
|
|
@ -217,7 +217,16 @@
|
|||
</button>
|
||||
</bubble-menu>
|
||||
|
||||
<editor-content class="editor__content" :editor="editor" v-if="editor" />
|
||||
<editor-content
|
||||
class="editor__content"
|
||||
:class="{ editorErrorStatus, editorIsFocused: focused }"
|
||||
:editor="editor"
|
||||
v-if="editor"
|
||||
ref="editorContentRef"
|
||||
/>
|
||||
<p v-if="editorErrorMessage" class="text-sm text-mbz-danger">
|
||||
{{ editorErrorMessage }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -249,7 +258,7 @@ import Underline from "@tiptap/extension-underline";
|
|||
import Link from "@tiptap/extension-link";
|
||||
import { AutoDir } from "./Editor/Autodir";
|
||||
// import sanitizeHtml from "sanitize-html";
|
||||
import { computed, inject, onBeforeUnmount, watch } from "vue";
|
||||
import { computed, inject, onBeforeUnmount, ref, watch } from "vue";
|
||||
import { Dialog } from "@/plugins/dialog";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useMutation } from "@vue/apollo-composable";
|
||||
|
@ -269,6 +278,7 @@ import FormatQuoteClose from "vue-material-design-icons/FormatQuoteClose.vue";
|
|||
import Undo from "vue-material-design-icons/Undo.vue";
|
||||
import Redo from "vue-material-design-icons/Redo.vue";
|
||||
import Placeholder from "@tiptap/extension-placeholder";
|
||||
import { useFocusWithin } from "@vueuse/core";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
|
@ -279,11 +289,13 @@ const props = withDefaults(
|
|||
currentActor: IPerson;
|
||||
placeholder?: string;
|
||||
headingLevel?: Level[];
|
||||
required?: boolean;
|
||||
}>(),
|
||||
{
|
||||
mode: "description",
|
||||
maxSize: 100_000_000,
|
||||
headingLevel: () => [3, 4, 5],
|
||||
required: false,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -333,7 +345,7 @@ const editor = useEditor({
|
|||
"aria-label": ariaLabel.value ?? "",
|
||||
role: "textbox",
|
||||
class:
|
||||
"prose dark:prose-invert prose-sm lg:prose-lg xl:prose-xl bg-zinc-50 dark:bg-zinc-700 focus:outline-none !max-w-full",
|
||||
"prose dark:prose-invert prose-sm lg:prose-lg xl:prose-xl bg-white dark:bg-zinc-700 !max-w-full",
|
||||
},
|
||||
transformPastedHTML: transformPastedHTML,
|
||||
},
|
||||
|
@ -373,8 +385,18 @@ const editor = useEditor({
|
|||
onUpdate: () => {
|
||||
emit("update:modelValue", editor.value?.getHTML());
|
||||
},
|
||||
onBlur: () => {
|
||||
checkEditorEmpty();
|
||||
},
|
||||
onFocus: () => {
|
||||
editorErrorStatus.value = false;
|
||||
editorErrorMessage.value = "";
|
||||
},
|
||||
});
|
||||
|
||||
const editorContentRef = ref(null);
|
||||
const { focused } = useFocusWithin(editorContentRef);
|
||||
|
||||
watch(value, (val: string) => {
|
||||
if (!editor.value) return;
|
||||
if (val !== editor.value.getHTML()) {
|
||||
|
@ -470,6 +492,18 @@ defineExpose({ replyToComment, focus });
|
|||
onBeforeUnmount(() => {
|
||||
editor.value?.destroy();
|
||||
});
|
||||
|
||||
const editorErrorStatus = ref(false);
|
||||
const editorErrorMessage = ref("");
|
||||
|
||||
const isEmpty = computed(
|
||||
() => props.required === true && editor.value?.isEmpty === true
|
||||
);
|
||||
|
||||
const checkEditorEmpty = () => {
|
||||
editorErrorStatus.value = isEmpty.value;
|
||||
editorErrorMessage.value = isEmpty.value ? t("You need to enter a text") : "";
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@use "@/styles/_mixins" as *;
|
||||
|
@ -523,14 +557,8 @@ onBeforeUnmount(() => {
|
|||
&__content {
|
||||
div.ProseMirror {
|
||||
min-height: 2.5rem;
|
||||
box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1);
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dbdbdb;
|
||||
padding: 12px 6px;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
|
@ -655,4 +683,19 @@ onBeforeUnmount(() => {
|
|||
.mention[data-id] {
|
||||
@apply inline-block border border-zinc-600 dark:border-zinc-300 rounded py-0.5 px-1;
|
||||
}
|
||||
|
||||
.editor__content > div {
|
||||
@apply border rounded border-[#6b7280];
|
||||
}
|
||||
|
||||
.editorIsFocused > div {
|
||||
@apply ring-2 ring-[#2563eb] outline-2 outline outline-offset-2 outline-transparent;
|
||||
}
|
||||
|
||||
.editorErrorStatus {
|
||||
@apply border-red-500;
|
||||
}
|
||||
.editor__content p.is-editor-empty:first-child::before {
|
||||
@apply text-slate-300;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -17,7 +17,6 @@ export function useGroupMembers(
|
|||
groupName: Ref<string>,
|
||||
options: useGroupMembersOptions = {}
|
||||
) {
|
||||
console.debug("useGroupMembers", options);
|
||||
const { result, error, loading, onResult, onError, refetch, fetchMore } =
|
||||
useQuery<
|
||||
{
|
||||
|
|
|
@ -13,6 +13,9 @@ export const COMMENT_FIELDS_FRAGMENT = gql`
|
|||
actor {
|
||||
...ActorFragment
|
||||
}
|
||||
attributedTo {
|
||||
...ActorFragment
|
||||
}
|
||||
totalReplies
|
||||
insertedAt
|
||||
updatedAt
|
||||
|
|
|
@ -12,6 +12,9 @@ export const CONVERSATION_QUERY_FRAGMENT = gql`
|
|||
lastComment {
|
||||
...CommentFields
|
||||
}
|
||||
originComment {
|
||||
...CommentFields
|
||||
}
|
||||
participants {
|
||||
...ActorFragment
|
||||
}
|
||||
|
@ -19,6 +22,12 @@ export const CONVERSATION_QUERY_FRAGMENT = gql`
|
|||
id
|
||||
uuid
|
||||
title
|
||||
organizerActor {
|
||||
id
|
||||
}
|
||||
attributedTo {
|
||||
id
|
||||
}
|
||||
picture {
|
||||
id
|
||||
url
|
||||
|
|
|
@ -1643,5 +1643,7 @@
|
|||
"Visit {instance_domain}": "Visit {instance_domain}",
|
||||
"Software details: {software_details}": "Software details: {software_details}",
|
||||
"Only instances with an application actor can be followed": "Only instances with an application actor can be followed",
|
||||
"Domain or instance name": "Domain or instance name"
|
||||
"Domain or instance name": "Domain or instance name",
|
||||
"You need to enter a text": "You need to enter a text",
|
||||
"Error while adding tag: {error}": "Error while adding tag: {error}"
|
||||
}
|
||||
|
|
|
@ -1636,5 +1636,7 @@
|
|||
"Visit {instance_domain}": "Visiter {instance_domain}",
|
||||
"Software details: {software_details}": "Détails du logiciel : {software_details}",
|
||||
"Only instances with an application actor can be followed": "Seules les instances avec un acteur application peuvent être suivies",
|
||||
"Domain or instance name": "Domaine ou nom de l'instance"
|
||||
"Domain or instance name": "Domaine ou nom de l'instance",
|
||||
"You need to enter a text": "Vous devez entrer un texte",
|
||||
"Error while adding tag: {error}": "Erreur lors de l'ajout d'un tag : {error}"
|
||||
}
|
||||
|
|
132
src/i18n/hu.json
132
src/i18n/hu.json
|
@ -16,7 +16,7 @@
|
|||
"A cookie is a small file containing information that is sent to your computer when you visit a website. When you visit the site again, the cookie allows that site to recognize your browser. Cookies may store user preferences and other information. You can configure your browser to refuse all cookies. However, this may result in some website features or services partially working. Local storage works the same way but allows you to store more data.": "A süti egy információt tartalmazó kis fájl, amelyet akkor küld el a számítógépe, ha meglátogat egy weboldalt. Amikor újra meglátogatja a weboldalt, akkor a süti lehetővé teszi annak az oldalnak, hogy felismerje a böngészőjét. A sütik tárolhatnak felhasználói beállításokat vagy egyéb információkat. Beállíthatja a böngészőjét úgy, hogy utasítson vissza minden sütit. Azonban ez azt eredményezheti, hogy néhány weboldalon a funkciók vagy a szolgáltatások csak részlegesen működnek. A helyi tároló hasonlóan működik, de több adat tárolását teszi lehetővé.",
|
||||
"A discussion has been created or updated": "Egy megbeszélés létre lett hozva vagy frissítve lett",
|
||||
"A federated software": "Egy föderált szoftver",
|
||||
"A fediverse account URL to follow for event updates": "Egy födiverzum-fiók URL az esemény frissítéseinek követéséhez",
|
||||
"A fediverse account URL to follow for event updates": "Egy Födiverzum-fiók webcíme az esemény frissítéseinek követéséhez",
|
||||
"A few lines about your group": "Néhány sor a csoportjáról",
|
||||
"A link to a page presenting the event schedule": "Az esemény ütemtervét bemutató oldalra mutató hivatkozás",
|
||||
"A link to a page presenting the price options": "Az árválasztékot bemutató oldalra mutató hivatkozás",
|
||||
|
@ -41,8 +41,8 @@
|
|||
"About Mobilizon": "A Mobilizon névjegye",
|
||||
"About anonymous participation": "A névtelen részvételről",
|
||||
"About instance": "A példány névjegye",
|
||||
"About this event": "Erről az eseményről",
|
||||
"About this instance": "Erről a példányról",
|
||||
"About this event": "Az esemény nébjegye",
|
||||
"About this instance": "A példány névjegye",
|
||||
"About {instance}": "A(z) {instance} névjegye",
|
||||
"Accept": "Elfogadás",
|
||||
"Accept follow": "Követés elfogadása",
|
||||
|
@ -57,7 +57,7 @@
|
|||
"Access group todo-lists": "Csoport teendőlistáinak elérése",
|
||||
"Access organized events": "Szervezett események elérése",
|
||||
"Access participations": "Résztvevők elérése",
|
||||
"Access your group's resources": "Csoport bejegyzéseinek elérése",
|
||||
"Access your group's resources": "A csoport erőforrásainak elérése",
|
||||
"Accessibility": "Akadálymentesítés",
|
||||
"Accessible only by link": "Csak hivatkozáson keresztül érhető el",
|
||||
"Accessible only to members": "Csak tagoknak érhető el",
|
||||
|
@ -84,7 +84,7 @@
|
|||
"Add new…": "Új hozzáadása…",
|
||||
"Add picture": "Kép hozzáadása",
|
||||
"Add some tags": "Címkék hozzáadása",
|
||||
"Add to my calendar": "Hozzáadás a naptáramhoz",
|
||||
"Add to my calendar": "Hozzáadás a saját naptárhoz",
|
||||
"Additional comments": "További hozzászólások",
|
||||
"Admin": "Adminisztrátor",
|
||||
"Admin dashboard": "Adminisztrátori vezérlőpult",
|
||||
|
@ -98,7 +98,7 @@
|
|||
"All the places have already been taken": "Már az összes helyet elfoglalták",
|
||||
"Allow all comments from users with accounts": "Az összes hozzászólás engedélyezése a bejelentkezett felhasználóktól",
|
||||
"Allow registrations": "Regisztrációk engedélyezése",
|
||||
"An URL to an external ticketing platform": "Egy URL egy külső jegyértékesítő platformhoz",
|
||||
"An URL to an external ticketing platform": "Egy külső jegyértékesítő platform webcíme",
|
||||
"An error has occured while refreshing the page.": "Hiba történt az oldal frissítésekor.",
|
||||
"An error has occured. Sorry about that. You may try to reload the page.": "Hiba történt. Sajnáljuk. Megpróbálhatja újratölteni az oldalt.",
|
||||
"An ethical alternative": "Egy etikus alternatíva",
|
||||
|
@ -146,11 +146,11 @@
|
|||
"Ask your instance admin to {enable_feature}.": "Kérje meg a példány adminisztrátorát, hogy {enable_feature}.",
|
||||
"Assigned to": "Hozzárendelve ehhez",
|
||||
"Atom feed for events and posts": "Atom hírforrás az eseményekhez és a bejegyzésekhez",
|
||||
"Attending": "Részt vesz",
|
||||
"Attending": "Részvétel",
|
||||
"Authorize": "Engedélyezés",
|
||||
"Authorize application": "Alkalmazás engedélyezése",
|
||||
"Authorized on {authorization_date}": "Engedélyezve: {authorization_date}",
|
||||
"Autorize this application to access your account?": "Engedélyezi, hogy ez az alkalmazás hozzáférjen a fiókjához?",
|
||||
"Autorize this application to access your account?": "Engedélyezi, hogy az alkalmazás hozzáférjen a fiókjához?",
|
||||
"Avatar": "Profilkép",
|
||||
"Back to group list": "Vissza a csoportokhoz",
|
||||
"Back to homepage": "Vissza a kezdőlapra",
|
||||
|
@ -183,8 +183,8 @@
|
|||
"Cancel edition": "Szerkesztés megszakítása",
|
||||
"Cancel follow request": "Követési kérés megszakítása",
|
||||
"Cancel membership request": "Tagsági kérés megszakítása",
|
||||
"Cancel my participation request…": "Részvételi kérésem megszakítása…",
|
||||
"Cancel my participation…": "Részvételem megszakítása…",
|
||||
"Cancel my participation request…": "Saját részvételi kérés visszavonása…",
|
||||
"Cancel my participation…": "Saját részvétel visszavonása…",
|
||||
"Cancelled": "Törölve",
|
||||
"Cancelled: Won't happen": "Törölve: nem fog megtörténni",
|
||||
"Categories": "Kategóriák",
|
||||
|
@ -193,9 +193,9 @@
|
|||
"Category list": "Kategóriák",
|
||||
"Change": "Változtatás",
|
||||
"Change email": "E-mail-cím megváltoztatása",
|
||||
"Change my email": "E-mail-címem megváltoztatása",
|
||||
"Change my identity…": "Személyazonosságom megváltoztatása…",
|
||||
"Change my password": "Jelszavam megváltoztatása",
|
||||
"Change my email": "Saját e-mail-cím megváltoztatása",
|
||||
"Change my identity…": "Saját személyazonosság megváltoztatása…",
|
||||
"Change my password": "Saját jelszó megváltoztatása",
|
||||
"Change role": "Szerep megváltoztatása",
|
||||
"Change the filters.": "Módosítsa a szűrőket.",
|
||||
"Change timezone": "Időzóna megváltoztatása",
|
||||
|
@ -224,8 +224,8 @@
|
|||
"Comments": "Hozzászólások",
|
||||
"Comments are closed for everybody else.": "A hozzászólások le vannak zárva mindenki más számára.",
|
||||
"Confirm": "Megerősítés",
|
||||
"Confirm my participation": "Részvételem megerősítése",
|
||||
"Confirm my particpation": "Részvételem megerősítése",
|
||||
"Confirm my participation": "Részvétel megerősítése",
|
||||
"Confirm my particpation": "Részvétel megerősítése",
|
||||
"Confirm participation": "Részvétel megerősítése",
|
||||
"Confirm user": "Felhasználó megerősítése",
|
||||
"Confirmed": "Megerősítve",
|
||||
|
@ -236,7 +236,7 @@
|
|||
"Continue": "Folytatás",
|
||||
"Continue editing": "Szerkesztés folytatása",
|
||||
"Cookies and Local storage": "Sütik és helyi tároló",
|
||||
"Copy URL to clipboard": "URL másolás a vágólapra",
|
||||
"Copy URL to clipboard": "Webcím másolás a vágólapra",
|
||||
"Copy details to clipboard": "Részletek másolása a vágólapra",
|
||||
"Country": "Ország",
|
||||
"Create": "Létrehozás",
|
||||
|
@ -272,7 +272,7 @@
|
|||
"Current identity has been changed to {identityName} in order to manage this event.": "A jelenlegi személyazonosság megváltozott {identityName} személyazonosságra az esemény kezelése érdekében.",
|
||||
"Current page": "Jelenlegi oldal",
|
||||
"Custom": "Egyéni",
|
||||
"Custom URL": "Egyéni URL",
|
||||
"Custom URL": "Egyéni webcím",
|
||||
"Custom text": "Egyéni szöveg",
|
||||
"Daily email summary": "Napi e-mailes összegzés",
|
||||
"Dark": "Sötét",
|
||||
|
@ -297,7 +297,7 @@
|
|||
"Delete everything": "Minden törlése",
|
||||
"Delete group": "Csoport törlése",
|
||||
"Delete group discussions": "Csoport témáinak törlése",
|
||||
"Delete group posts": "Csoport bejegyzéseinek törlése",
|
||||
"Delete group posts": "Csoportbejegyzések törlése",
|
||||
"Delete group resources": "Csoport erőforrásainak törlése",
|
||||
"Delete my account": "Saját fiók törlése",
|
||||
"Delete post": "Bejegyzés törlése",
|
||||
|
@ -310,7 +310,7 @@
|
|||
"Deleting comment": "Hozzászólás törlése",
|
||||
"Deleting event": "Esemény törlése",
|
||||
"Deleting my account will delete all of my identities.": "A saját fiókom törlése törölni fogja az összes személyazonosságomat is.",
|
||||
"Deleting your Mobilizon account": "Az Ön Mobilizon-fiókjának törlése",
|
||||
"Deleting your Mobilizon account": "A saját Mobilizon-fiókjának törlése",
|
||||
"Demote": "Lefokozás",
|
||||
"Describe your event": "Írja le az eseményt",
|
||||
"Description": "Leírás",
|
||||
|
@ -355,7 +355,7 @@
|
|||
"Enabled": "Engedélyezve",
|
||||
"Ends on…": "Befejeződik…",
|
||||
"Enter the code displayed on your device": "Adja meg az eszközén megjelenített kódot",
|
||||
"Enter the link URL": "Adja meg a hivatkozás URL-ét",
|
||||
"Enter the link URL": "Adja meg a hivatkozás webcímét",
|
||||
"Enter your email address below, and we'll email you instructions on how to change your password.": "Adja meg lent az e-mail-címét, és elküldjük e-mailben az utasításokat, hogy hogyan változtathatja meg a jelszavát.",
|
||||
"Enter your own privacy policy. HTML tags allowed. The {mobilizon_privacy_policy} is provided as template.": "Adja meg a saját adatvédelmi irányelveit. A HTML címkék engedélyezettek. A {mobilizon_privacy_policy} meg van adva sablonként.",
|
||||
"Enter your own terms. HTML tags allowed. The {mobilizon_terms} are provided as template.": "Adja meg a saját használati feltételeit. A HTML címkék engedélyezettek. A {mobilizon_terms} meg van adva sablonként.",
|
||||
|
@ -377,7 +377,7 @@
|
|||
"Ethical alternative to Facebook events, groups and pages, Mobilizon is a <b>tool designed to serve you</b>. Period.": "Etikus alternatíva a Facebook eseményekre, csoportokra és oldalakra. A Mobilizon egy olyan <b>eszköz, amelyet úgy terveztek, hogy Önt szolgálja</b>. És pont.",
|
||||
"Ethical alternative to Facebook events, groups and pages, Mobilizon is a {tool_designed_to_serve_you}. Period.": "A facebookos események, csoportok és oldalak etikus alternatívája, a Mobilizon egy olyan {tool_designed_to_serve_you}. Pont.",
|
||||
"Event": "Esemény",
|
||||
"Event URL": "Esemény URL",
|
||||
"Event URL": "Esemény webcíme",
|
||||
"Event already passed": "Az esemény már elmúlt",
|
||||
"Event cancelled": "Esemény törölve",
|
||||
"Event creation": "Eseménylétrehozás",
|
||||
|
@ -464,7 +464,7 @@
|
|||
"Group": "Csoport",
|
||||
"Group Followers": "Követők csoportosítása",
|
||||
"Group Members": "Csoporttagok",
|
||||
"Group URL": "Csoport URL",
|
||||
"Group URL": "Csoport webcíme",
|
||||
"Group activity": "Csoporttevékenység",
|
||||
"Group address": "Csoport címe",
|
||||
"Group description body": "Csoport leírásának törzse",
|
||||
|
@ -528,13 +528,13 @@
|
|||
"Instance Name": "Példány neve",
|
||||
"Instance Privacy Policy": "Példány adatvédelmi irányelve",
|
||||
"Instance Privacy Policy Source": "Példány adatvédelmi irányelvének forrása",
|
||||
"Instance Privacy Policy URL": "Példány adatvédelmi irányelvének URL-je",
|
||||
"Instance Privacy Policy URL": "Példány adatvédelmi irányelvének webcíme",
|
||||
"Instance Rules": "Példány szabályai",
|
||||
"Instance Short Description": "Példány rövid leírása",
|
||||
"Instance Slogan": "Példány szlogenje",
|
||||
"Instance Terms": "Példány használati feltételei",
|
||||
"Instance Terms Source": "Példány használati feltételeinek forrása",
|
||||
"Instance Terms URL": "Példány használati feltételeinek URL-e",
|
||||
"Instance Terms URL": "Példány használati feltételeinek webcíme",
|
||||
"Instance administrator": "Példány adminisztrátora",
|
||||
"Instance configuration": "Példány beállítása",
|
||||
"Instance feeds": "Példány hírforrásai",
|
||||
|
@ -759,7 +759,7 @@
|
|||
"Only group members can access discussions": "Csak csoporttagok férhetnek hozzá a megbeszélésekhez",
|
||||
"Only group moderators can create, edit and delete events.": "Csak a csoport moderátorai hozhatnak létre, szerkeszthetnek és törölhetnek eseményeket.",
|
||||
"Only group moderators can create, edit and delete posts.": "Csak a csoport moderátorai hozhatnak létre, szerkeszthetnek és törölhetnek bejegyzéseket.",
|
||||
"Only registered users may fetch remote events from their URL.": "Csak regisztrált felhasználók kérhetik le a távoli eseményeket az URL-ükről.",
|
||||
"Only registered users may fetch remote events from their URL.": "Csak regisztrált felhasználók kérhetik le a távoli eseményeket a webcímükről.",
|
||||
"Open": "Megnyitás",
|
||||
"Open a topic on our forum": "Téma nyitása a fórumunkon",
|
||||
"Open an issue on our bug tracker (advanced users)": "Jegy nyitása a hibakövetőnkben (haladó felhasználóknak)",
|
||||
|
@ -784,7 +784,7 @@
|
|||
"Otherwise this identity will just be removed from the group administrators.": "Egyébként ez a személyazonosság el lesz távolítva a csoport adminisztrátoraiból.",
|
||||
"Owncast": "Owncast",
|
||||
"Page": "Oldal",
|
||||
"Page limited to my group (asks for auth)": "Az oldal korlátozva van a csoportomra (hitelesítést kér)",
|
||||
"Page limited to my group (asks for auth)": "Az oldal korlátozva van a saját csoportomra (hitelesítést kér)",
|
||||
"Page not found": "Az oldal nem található",
|
||||
"Parent folder": "Szülőmappa",
|
||||
"Partially accessible with a wheelchair": "Részlegesen közelíthető meg kerekesszékkel",
|
||||
|
@ -822,7 +822,7 @@
|
|||
"Popular groups close to you": "Önhöz közeli népszerű csoportok",
|
||||
"Popular groups nearby {position}": "Népszerű csoportok {position} közelében",
|
||||
"Post": "Bejegyzés",
|
||||
"Post URL": "Bejegyzés URL-e",
|
||||
"Post URL": "Bejegyzés webcíme",
|
||||
"Post a comment": "Hozzászólás beküldése",
|
||||
"Post a reply": "Válasz beküldése",
|
||||
"Post body": "Bejegyzés törzse",
|
||||
|
@ -858,7 +858,7 @@
|
|||
"Publication date": "Közzététel dátuma",
|
||||
"Publish": "Közzététel",
|
||||
"Publish events": "Események közzététele",
|
||||
"Publish group posts": "Csoport bejegyzéseinek közzététele",
|
||||
"Publish group posts": "Csoportbejegyzések közzététele",
|
||||
"Published by {name}": "Közzétette: {name}",
|
||||
"Published events with <b>{comments}</b> comments and <b>{participations}</b> confirmed participations": "Közzétett események <b>{comments}</b> hozzászólással és <b>{participations}</b> megerősített részvétellel",
|
||||
"Published events with {comments} comments and {participations} confirmed participations": "Események közzétéve {comments} hozzászólással és {participations} megerősített résztvevővel",
|
||||
|
@ -892,7 +892,7 @@
|
|||
"Remember my participation in this browser": "Emlékezzen a részvételemre ebben a böngészőben",
|
||||
"Remove": "Eltávolítás",
|
||||
"Remove link": "Hivatkozás eltávolítása",
|
||||
"Remove uploaded media": "Feltöltött média eltávolítása",
|
||||
"Remove uploaded media": "Feltöltött média törlése",
|
||||
"Rename": "Átnevezés",
|
||||
"Rename resource": "Erőforrás átnevezése",
|
||||
"Reopen": "Újranyitás",
|
||||
|
@ -900,8 +900,8 @@
|
|||
"Reply": "Válasz",
|
||||
"Report": "Jelentés",
|
||||
"Report #{reportNumber}": "#{reportNumber} jelentés",
|
||||
"Report as ham": "Jelentés nem kéretlenként",
|
||||
"Report as spam": "Jelentés kéretlenként",
|
||||
"Report as ham": "Jelentés hasznosként",
|
||||
"Report as spam": "Jelentés kéretlen tartalomként",
|
||||
"Report as undetected spam": "Jelentés nem észlelt kéretlen tartalomként",
|
||||
"Report reason": "Jelentés oka",
|
||||
"Report status": "Állapotjelentés",
|
||||
|
@ -924,10 +924,10 @@
|
|||
"Resent confirmation email": "Megerősítő e-mail újraküldve",
|
||||
"Reset": "Visszaállítás",
|
||||
"Reset filters": "Szűrők alaphelyzetbe állítása",
|
||||
"Reset my password": "Jelszavam visszaállítása",
|
||||
"Reset my password": "Saját jelszó visszaállítása",
|
||||
"Reset password": "Jelszó visszaállítása",
|
||||
"Resolved": "Megoldva",
|
||||
"Resource provided is not an URL": "A megadott erőforrás nem URL",
|
||||
"Resource provided is not an URL": "A megadott erőforrás nem webcím",
|
||||
"Resources": "Erőforrások",
|
||||
"Restricted": "Korlátozott",
|
||||
"Return to the group page": "Visszatérés a csoport oldalára",
|
||||
|
@ -935,13 +935,13 @@
|
|||
"Right now": "Épp most",
|
||||
"Role": "Szerep",
|
||||
"Rules": "Szabályok",
|
||||
"SSL and it's successor TLS are encryption technologies to secure data communications when using the service. You can recognize an encrypted connection in your browser's address line when the URL begins with {https} and the lock icon is displayed in your browser's address bar.": "Az SSL és utódja, a TLS, titkosítási technológiák a szolgáltatás használatakor történő adatkommunikációk biztonságossá tételéhez. Arról ismerhet fel egy titkosított kapcsolatot a böngészője címsorában, hogy az URL {https} kezdetű, és lakat ikon jelenik meg a böngészője címsávjában.",
|
||||
"SSL and it's successor TLS are encryption technologies to secure data communications when using the service. You can recognize an encrypted connection in your browser's address line when the URL begins with {https} and the lock icon is displayed in your browser's address bar.": "Az SSL és utódja, a TLS, titkosítási technológiák a szolgáltatás használatakor történő adatkommunikációk biztonságossá tételéhez. Arról ismerhet fel egy titkosított kapcsolatot a böngészője címsorában, hogy a webcím {https} kezdetű, és lakat ikon jelenik meg a böngészője címsávjában.",
|
||||
"SSL/TLS": "SSL/TLS",
|
||||
"Save": "Mentés",
|
||||
"Save draft": "Piszkozat mentése",
|
||||
"Schedule": "Ütemterv",
|
||||
"Search": "Keresés",
|
||||
"Search events, groups, etc.": "Események, csoportok és egyebek keresése",
|
||||
"Search events, groups, etc.": "Események, csoportok stb. keresése",
|
||||
"Search target": "Cél keresése",
|
||||
"Searching…": "Keresés…",
|
||||
"Select a category": "Válasszon egy kategóriát",
|
||||
|
@ -959,8 +959,8 @@
|
|||
"Send password reset": "Jelszó-visszaállítás küldése",
|
||||
"Send the confirmation email again": "A megerősítő e-mail újraküldése",
|
||||
"Send the report": "A jelentés küldése",
|
||||
"Set an URL to a page with your own privacy policy.": "URL beállítása a saját adatvédelmi irányelveit tartalmazó oldalra.",
|
||||
"Set an URL to a page with your own terms.": "URL beállítása a saját használati feltételeit tartalmazó oldalra.",
|
||||
"Set an URL to a page with your own privacy policy.": "Állítsa be a webcímet a saját adatvédelmi irányelveit tartalmazó oldalra.",
|
||||
"Set an URL to a page with your own terms.": "Állítsa be a webcímet a saját felhasználási feltételeit tartalmazó oldalra.",
|
||||
"Settings": "Beállítások",
|
||||
"Share": "Megosztás",
|
||||
"Share this event": "Az esemény megosztása",
|
||||
|
@ -1010,15 +1010,15 @@
|
|||
"Text": "Szöveg",
|
||||
"Thanks a lot, your feedback was submitted!": "Köszönjük, beküldte a visszajelzést!",
|
||||
"That you follow or of which you are a member": "Amelyet Ön követ, vagy amelynek Ön tagja",
|
||||
"The Big Blue Button video teleconference URL": "A Big Blue Button videótelefon-konferencia URL-e",
|
||||
"The Google Meet video teleconference URL": "A Google Meet videótelefon-konferencia URL-e",
|
||||
"The Jitsi Meet video teleconference URL": "A Jitsi Meet videótelefon-konferencia URL-e",
|
||||
"The Microsoft Teams video teleconference URL": "A Microsoft Teams videótelefon-konferencia URL-e",
|
||||
"The URL of a pad where notes are being taken collaboratively": "A jegyzettömb URL-e, ahol a jegyzeteket közösen készítik el",
|
||||
"The URL of a poll where the choice for the event date is happening": "Egy szavazás URL-e, ahol az esemény dátumának kiválasztása történik",
|
||||
"The URL where the event can be watched live": "Az URL, ahol az esemény élőben nézhető",
|
||||
"The URL where the event live can be watched again after it has ended": "Az URL, ahol az élő esemény újra megnézhető, miután befejeződött",
|
||||
"The Zoom video teleconference URL": "A Zoom videótelefon-konferencia URL-e",
|
||||
"The Big Blue Button video teleconference URL": "A Big Blue Button videókonferencia webcíme",
|
||||
"The Google Meet video teleconference URL": "A Google Meet videókonferencia webcíme",
|
||||
"The Jitsi Meet video teleconference URL": "A Jitsi Meet videókonferencia webcíme",
|
||||
"The Microsoft Teams video teleconference URL": "A Microsoft Teams videókonferencia webcíme",
|
||||
"The URL of a pad where notes are being taken collaboratively": "A jegyzettömb webcíme, ahol a jegyzeteket közösen készítik el",
|
||||
"The URL of a poll where the choice for the event date is happening": "Egy szavazás webcíme, ahol az esemény dátumának kiválasztása történik",
|
||||
"The URL where the event can be watched live": "A webcím, ahol az esemény élőben nézhető",
|
||||
"The URL where the event live can be watched again after it has ended": "A webcím, ahol az élő esemény újra megnézhető, miután befejeződött",
|
||||
"The Zoom video teleconference URL": "A Zoom videókonferencia webcíme",
|
||||
"The account's email address was changed. Check your emails to verify it.": "A fiók e-mail-címe megváltozott. Nézze meg az e-mailjeit az ellenőrzéséhez.",
|
||||
"The actual number of participants may differ, as this event is hosted on another instance.": "A résztvevők tényleges száma eltérhet, mivel ez az esemény egy másik példányon van kiszolgálva.",
|
||||
"The calc will be created on {service}": "A táblázat itt lesz létrehozva: {service}",
|
||||
|
@ -1067,7 +1067,7 @@
|
|||
"The post {post} was deleted by {profile}.": "A(z) {post} bejegyzést {profile} törölte.",
|
||||
"The post {post} was updated by {profile}.": "A(z) {post} bejegyzést {profile} frissítette.",
|
||||
"The provided application was not found.": "A megadott alkalmazás nem található.",
|
||||
"The report contents (eventual comments and event) and the reported profile details will be transmitted to Akismet.": "A jelentés tartalma (a hozzászólások és az esemény) és a jelentett profil részletei el lesznek küldve az Akismetnek.",
|
||||
"The report contents (eventual comments and event) and the reported profile details will be transmitted to Akismet.": "A jelentés tartalma (az esetleges hozzászólások és az esemény), valamint a jelentett profil részletei el lesznek küldve az Akismetnek.",
|
||||
"The report will be sent to the moderators of your instance. You can explain why you report this content below.": "A jelentés el lesz küldve a példánya moderátorainak. Elmagyarázhatja alább, hogy miért jelenti ezt a tartalmat.",
|
||||
"The selected picture is too heavy. You need to select a file smaller than {size}.": "A kiválasztott kép túl nagy. Egy {size} méretűnél kisebb fájlt kell kiválasztania.",
|
||||
"The technical details of the error can help developers solve the problem more easily. Please add them to your feedback.": "A hiba műszaki részletei segítenek a fejlesztőknek, hogy könnyebben megoldják a problémát. Adja hozzá a visszajelzéséhez.",
|
||||
|
@ -1084,17 +1084,17 @@
|
|||
"These feeds contain event data for the events for which any of your profiles is a participant or creator. You should keep these private. You can find feeds for specific profiles on each profile edition page.": "Ezek a hírforrások eseményadatokat tartalmaznak azon eseményekhez, amelyeknél a profiljai bármelyike résztvevő vagy létrehozó. Ezeket bizalmasan kell tartania. Adott profilokhoz találhat hírforrásokat az egyes profilszerkesztő oldalakon.",
|
||||
"These feeds contain event data for the events for which this specific profile is a participant or creator. You should keep these private. You can find feeds for all of your profiles into your notification settings.": "Ezek a hírforrások eseményadatokat tartalmaznak azon eseményekhez, amelyeknél ez a bizonyos profil résztvevő vagy létrehozó. Ezeket bizalmasan kell tartania. Az összes profiljához találhat hírforrásokat az értesítési beállításaiban.",
|
||||
"This Mobilizon instance and this event organizer allows anonymous participations, but requires validation through email confirmation.": "Ez a Mobilizon példány és ez az eseményszervező megengedi a névtelen részvételeket, de ellenőrzés szükséges e-mailen keresztüli megerősítéssel.",
|
||||
"This URL doesn't seem to be valid": "Ez az URL nem tűnik érvényesnek",
|
||||
"This URL is not supported": "Ez az URL nem támogatott",
|
||||
"This application will be able to access all of your informations and post content. Make sure you only approve applications you trust.": "Ez az alkalmazás hozzá fog férni az összes információjához és a bejegyzései tartalmához. Győződjön meg arról, hogy csak azokat az alkalmazásokat engedélyezi, melyekben megbízik.",
|
||||
"This application will be allowed to delete events": "Az alkalmazás törölheti az eseményeket",
|
||||
"This application will be allowed to delete group posts": "Az alkalmazás törölheti a bejegyzéseket a csoportokból",
|
||||
"This application will be allowed to publish events": "Az alkalmazás közzétehet eseményeket",
|
||||
"This application will be allowed to publish group posts": "Az alkalmazás közzétehet bejegyzéseket a csoportokban",
|
||||
"This application will be allowed to remove uploaded media": "Az alkalmazás törölheti a feltöltött médiafájlokat",
|
||||
"This application will be allowed to update events": "Az alkalmazás frissítheti az eseményeket",
|
||||
"This application will be allowed to update group posts": "Az alkalmazás frissítheti a bejegyzéseket a csoportokban",
|
||||
"This application will be allowed to upload media": "Az alkalmazás tölthet fel médiafájlokat",
|
||||
"This URL doesn't seem to be valid": "Ez a webcím nem tűnik érvényesnek",
|
||||
"This URL is not supported": "Ez a webcím nem támogatott",
|
||||
"This application will be able to access all of your informations and post content. Make sure you only approve applications you trust.": "Az alkalmazás eléri az összes információját és bejegyzését. Csak azokat az alkalmazásokat engedélyezze, melyekben megbízik.",
|
||||
"This application will be allowed to delete events": "Az alkalmazás jogosult lesz az események törlésére",
|
||||
"This application will be allowed to delete group posts": "Az alkalmazás jogosult lesz a csoportbejegyzések törlésére",
|
||||
"This application will be allowed to publish events": "Az alkalmazás jogosult lesz az események közzétételére",
|
||||
"This application will be allowed to publish group posts": "Az alkalmazás jogosult lesz csoportbejegyzések közzétételére",
|
||||
"This application will be allowed to remove uploaded media": "Az alkalmazás jogosult lesz a feltöltött médiatartalmak törlésére",
|
||||
"This application will be allowed to update events": "Az alkalmazás jogosult lesz az események frissítésére",
|
||||
"This application will be allowed to update group posts": "Az alkalmazás jogosult lesz a csoportbejegyzések frissítésére",
|
||||
"This application will be allowed to upload media": "Az alkalmazás jogosult lesz médiatartalmak feltöltésére",
|
||||
"This event has been cancelled.": "Ezt az eseményt törölték.",
|
||||
"This event is accessible only through it's link. Be careful where you post this link.": "Ez az esemény csak a hivatkozásán keresztül érhető el. Legyen óvatos, hogy hova küldi be ezt a hivatkozást.",
|
||||
"This group doesn't have a description yet.": "Ennek a csoportnak még nincs leírása.",
|
||||
|
@ -1123,7 +1123,7 @@
|
|||
"This user was not found": "Ez a felhasználó nem található",
|
||||
"This website isn't moderated and the data that you enter will be automatically destroyed every day at 00:01 (Paris timezone).": "Ez a weboldal nincs moderálva, és a beírt adatok automatikusan meg lesznek semmisítve minden nap 00:01-kor (Párizs időzóna).",
|
||||
"This week": "Ez a hét",
|
||||
"This weekend": "Ezen a hétvégén",
|
||||
"This weekend": "Ez a hétvége",
|
||||
"This will delete / anonymize all content (events, comments, messages, participations…) created from this identity.": "Ez törölni vagy névteleníteni fogja az ezzel a személyazonossággal létrehozott összes tartalmat (eseményeket, hozzászólásokat, üzeneteket, részvételeket…).",
|
||||
"Time in your timezone ({timezone})": "Az idő az Ön időzónájában ({timezone})",
|
||||
"Times in your timezone ({timezone})": "Az idők az Ön időzónájában ({timezone})",
|
||||
|
@ -1152,8 +1152,8 @@
|
|||
"Twitter account": "Twitter-fiók",
|
||||
"Type": "Típus",
|
||||
"Type or select a date…": "Gépeljen be vagy válasszon egy dátumot…",
|
||||
"URL": "URL",
|
||||
"URL copied to clipboard": "URL másolva a vágólapra",
|
||||
"URL": "Webcím",
|
||||
"URL copied to clipboard": "Webcím a vágólapra másolva",
|
||||
"Unable to copy to clipboard": "Nem lehet a vágólapra másolni",
|
||||
"Unable to create the group. One of the pictures may be too heavy.": "Nem lehet létrehozni a csoportot. A képek egyike esetleg túl nagy.",
|
||||
"Unable to create the profile. The avatar picture may be too heavy.": "Nem lehet létrehozni a profilt. A profilkép esetleg túl nagy.",
|
||||
|
@ -1184,7 +1184,7 @@
|
|||
"Update events": "Események frissítése",
|
||||
"Update group": "Csoport frissítése",
|
||||
"Update group discussions": "Csoport témáinak frissítése",
|
||||
"Update group posts": "Csoport bejegyzéseinek frissítése",
|
||||
"Update group posts": "Csoportbejegyzések frissítése",
|
||||
"Update group resources": "Csoport erőforrásainak frissítése",
|
||||
"Update my event": "Saját esemény frissítése",
|
||||
"Update post": "Bejegyzés frissítése",
|
||||
|
@ -1236,7 +1236,7 @@
|
|||
"We'll send you an email one hour before the event begins, to be sure you won't forget about it.": "Egy e-mailt fogunk küldeni Önnek az esemény kezdete előtt egy órával, hogy biztosan ne felejtse el azt.",
|
||||
"We'll use your timezone settings to send a recap of the morning of the event.": "Az Ön időzóna-beállításait fogjuk használni az esemény reggeli rövid összegzésének küldéséhez.",
|
||||
"Website": "Weboldal",
|
||||
"Website / URL": "Weboldal vagy URL",
|
||||
"Website / URL": "Weboldal vagy webcím",
|
||||
"Weekly email summary": "Heti e-mailes összegzés",
|
||||
"Welcome back {username}!": "Üdvözöljük, {username}!",
|
||||
"Welcome back!": "Üdvözöljük!",
|
||||
|
@ -1346,10 +1346,10 @@
|
|||
"You will find here all the events you have created or of which you are a participant, as well as events organized by groups you follow or are a member of.": "Itt megtalálja az összes eseményt, amelyeket létrehozott vagy amelyeknél Ön résztvevő, illetve az olyan csoportok által szervezett eseményeket, amelyeket Ön követ vagy amelyeknek tagja.",
|
||||
"You will receive notifications about this group's public activity depending on %{notification_settings}.": "Értesítéseket fog kapni ennek a csoportnak a nyilvános tevékenységéről az %{notification_settings} függően.",
|
||||
"You wish to participate to the following event": "Részt kíván venni a következő eseményen",
|
||||
"You'll be able to revoke access for this application in your account settings.": "Az alkalmazás hozzáférését a fiókbeállításokban vonhatja vissza.",
|
||||
"You'll be able to revoke access for this application in your account settings.": "Az alkalmazás hozzáférése a fiókbeállításokban vonható vissza.",
|
||||
"You'll get a weekly recap every Monday for upcoming events, if you have any.": "Heti rövid összegzést fog kapni minden hétfőn a közelgő eseményekről, ha van ilyen.",
|
||||
"You'll need to change the URLs where there were previously entered.": "Meg kell majd változtatnia az URL-eket, ahol korábban meg lettek adva.",
|
||||
"You'll need to transmit the group URL so people may access the group's profile. The group won't be findable in Mobilizon's search or regular search engines.": "Át kell küldenie a csoport URL-jét, hogy az emberek hozzáférhessenek a csoport profiljához. A csoport nem lesz megtalálható a Mobilizon keresőjében vagy a szokásos keresőmotorokban.",
|
||||
"You'll need to change the URLs where there were previously entered.": "Meg kell majd változtatnia az webcímeket, ahol korábban meg lettek adva.",
|
||||
"You'll need to transmit the group URL so people may access the group's profile. The group won't be findable in Mobilizon's search or regular search engines.": "Át kell küldenie a csoport webcímét, hogy az emberek hozzáférhessenek a csoport profiljához. A csoport nem lesz megtalálható a Mobilizon keresőjében vagy a szokásos keresőmotorokban.",
|
||||
"You'll receive a confirmation email.": "Kapni fog egy megerősítő e-mailt.",
|
||||
"YouTube live": "YouTube élő",
|
||||
"YouTube replay": "YouTube ismétlés",
|
||||
|
|
|
@ -27,6 +27,16 @@ export const orugaConfig = {
|
|||
taginput: {
|
||||
itemClass: "taginput-item",
|
||||
rootClass: "taginput",
|
||||
containerClass: "taginput-container",
|
||||
expandedClass: "taginput-expanded",
|
||||
autocompleteClasses: {
|
||||
rootClass: "taginput-autocomplete",
|
||||
itemClass: "taginput-autocomplete-item",
|
||||
inputClasses: {
|
||||
rootClass: "taginput-input-wrapper",
|
||||
inputClass: "taginput-input",
|
||||
},
|
||||
},
|
||||
},
|
||||
autocomplete: {
|
||||
rootClass: "autocomplete",
|
||||
|
@ -57,6 +67,7 @@ export const orugaConfig = {
|
|||
datepicker: {
|
||||
iconNext: "ChevronRight",
|
||||
iconPrev: "ChevronLeft",
|
||||
boxClass: "datepicker-box",
|
||||
},
|
||||
modal: {
|
||||
rootClass: "modal",
|
||||
|
|
|
@ -155,6 +155,7 @@ export function iconForAddress(address: IAddress): IPOIIcon {
|
|||
}
|
||||
|
||||
export function addressFullName(address: IAddress): string {
|
||||
if (!address) return "";
|
||||
const { name, alternativeName } = addressToPoiInfos(address);
|
||||
if (name && alternativeName) {
|
||||
return `${name}, ${alternativeName}`;
|
||||
|
|
|
@ -8,6 +8,7 @@ export interface IConversation {
|
|||
id?: string;
|
||||
actor?: IActor;
|
||||
lastComment?: IComment;
|
||||
originComment?: IComment;
|
||||
comments: Paginate<IComment>;
|
||||
participants: IActor[];
|
||||
updatedAt: string;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
aria-required="true"
|
||||
required
|
||||
v-model="identity.name"
|
||||
@input="(event: any) => updateUsername(event.target.value)"
|
||||
@update:modelValue="(value: string) => updateUsername(value)"
|
||||
id="identity-display-name"
|
||||
dir="auto"
|
||||
expanded
|
||||
|
@ -740,6 +740,7 @@ const breadcrumbsLinks = computed(
|
|||
);
|
||||
|
||||
const updateUsername = (value: string) => {
|
||||
if (props.isUpdate) return;
|
||||
identity.value.preferredUsername = convertToUsername(value);
|
||||
};
|
||||
|
||||
|
|
|
@ -233,7 +233,7 @@ import {
|
|||
useRouteQuery,
|
||||
} from "vue-use-route-query";
|
||||
import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { computed, inject, ref } from "vue";
|
||||
import { computed, inject, ref, watch } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import CloudQuestion from "../../../node_modules/vue-material-design-icons/CloudQuestion.vue";
|
||||
|
@ -263,8 +263,26 @@ const { result: instancesResult } = useQuery<{
|
|||
{ debounce: 500 }
|
||||
);
|
||||
|
||||
watch([filterDomain, followStatus], () => {
|
||||
instancePage.value = 1;
|
||||
});
|
||||
|
||||
const instances = computed(() => instancesResult.value?.instances);
|
||||
|
||||
const instancesTotal = computed(() => instancesResult.value?.instances.total);
|
||||
const currentPageInstancesNumber = computed(
|
||||
() => instancesResult.value?.instances.elements.length
|
||||
);
|
||||
|
||||
// If we didn't found any instances on this page
|
||||
watch(instancesTotal, (newInstancesTotal) => {
|
||||
if (newInstancesTotal === 0) {
|
||||
instancePage.value = 1;
|
||||
} else if (currentPageInstancesNumber.value === 0) {
|
||||
instancePage.value = instancePage.value - 1;
|
||||
}
|
||||
});
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
useHead({
|
||||
title: computed(() => t("Federation")),
|
||||
|
|
|
@ -14,7 +14,11 @@
|
|||
]"
|
||||
/>
|
||||
<div
|
||||
v-if="conversation.event && !isCurrentActorAuthor"
|
||||
v-if="
|
||||
conversation.event &&
|
||||
!isCurrentActorAuthor &&
|
||||
isOriginCommentAuthorEventOrganizer
|
||||
"
|
||||
class="bg-mbz-yellow p-6 mb-3 rounded flex gap-2 items-center"
|
||||
>
|
||||
<Calendar :size="36" />
|
||||
|
@ -132,7 +136,11 @@
|
|||
>
|
||||
</form>
|
||||
<div
|
||||
v-else-if="conversation.event"
|
||||
v-else-if="
|
||||
conversation.event &&
|
||||
!isCurrentActorAuthor &&
|
||||
isOriginCommentAuthorEventOrganizer
|
||||
"
|
||||
class="bg-mbz-yellow p-6 rounded flex gap-2 items-center mt-3"
|
||||
>
|
||||
<Calendar :size="36" />
|
||||
|
@ -292,6 +300,16 @@ const isCurrentActorAuthor = computed(
|
|||
currentActor.value.id !== conversation.value?.actor?.id
|
||||
);
|
||||
|
||||
const isOriginCommentAuthorEventOrganizer = computed(
|
||||
() =>
|
||||
conversation.value?.originComment?.actor &&
|
||||
conversation.value?.event &&
|
||||
[
|
||||
conversation.value?.event?.organizerActor?.id,
|
||||
conversation.value?.event?.attributedTo?.id,
|
||||
].includes(conversation.value?.originComment?.actor.id)
|
||||
);
|
||||
|
||||
useHead({
|
||||
title: () => title.value,
|
||||
});
|
||||
|
|
|
@ -924,9 +924,28 @@ const handleError = (err: any) => {
|
|||
console.error(err);
|
||||
|
||||
if (err.graphQLErrors !== undefined) {
|
||||
err.graphQLErrors.forEach(({ message }: { message: string }) => {
|
||||
notifier?.error(message);
|
||||
});
|
||||
err.graphQLErrors.forEach(
|
||||
({
|
||||
message,
|
||||
field,
|
||||
}: {
|
||||
message: string | { slug?: string[] }[];
|
||||
field: string;
|
||||
}) => {
|
||||
if (
|
||||
field === "tags" &&
|
||||
Array.isArray(message) &&
|
||||
message.some((msg) => msg.slug)
|
||||
) {
|
||||
const finalMsg = message.find((msg) => msg.slug?.[0]);
|
||||
notifier?.error(
|
||||
t("Error while adding tag: {error}", { error: finalMsg?.slug?.[0] })
|
||||
);
|
||||
} else if (typeof message === "string") {
|
||||
notifier?.error(message);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -349,11 +349,10 @@ const { result: loggedUserResult } = useQuery<{ loggedUser: IUser }>(
|
|||
USER_NOTIFICATIONS
|
||||
);
|
||||
const loggedUser = computed(() => loggedUserResult.value?.loggedUser);
|
||||
const feedTokens = computed(
|
||||
() =>
|
||||
loggedUser.value?.feedTokens.filter(
|
||||
(token: IFeedToken) => token.actor === null
|
||||
)
|
||||
const feedTokens = computed(() =>
|
||||
loggedUser.value?.feedTokens.filter(
|
||||
(token: IFeedToken) => token.actor === null
|
||||
)
|
||||
);
|
||||
|
||||
const { result: webPushEnabledResult } = useQuery<{
|
||||
|
|
|
@ -94,7 +94,6 @@
|
|||
<o-field grouped>
|
||||
<o-field :label="t('City or region')" expanded label-for="setting-city">
|
||||
<full-address-auto-complete
|
||||
v-if="loggedUser?.settings"
|
||||
:resultType="AddressSearchType.ADMINISTRATIVE"
|
||||
v-model="address"
|
||||
:default-text="address?.description"
|
||||
|
|
|
@ -6,6 +6,7 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.CreateTest do
|
|||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Conversations.Conversation
|
||||
alias Mobilizon.Discussions.Comment
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Federation.ActivityPub.Transmogrifier
|
||||
alias Mobilizon.Service.HTTP.ActivityPub.Mock
|
||||
|
||||
|
@ -103,5 +104,57 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.CreateTest do
|
|||
{:ok, admin} = Mobilizon.Actors.get_actor_by_url("https://framapiaf.org/users/admin")
|
||||
assert participant_ids == MapSet.new([actor.id, admin.id])
|
||||
end
|
||||
|
||||
test "it creates conversations for received comments if we're concerned even with reply to an event" do
|
||||
actor_data = File.read!("test/fixtures/mastodon-actor.json") |> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, 1, fn
|
||||
%{method: :get, url: "https://framapiaf.org/users/admin"}, _opts ->
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body:
|
||||
actor_data
|
||||
|> Map.put("id", "https://framapiaf.org/users/admin")
|
||||
|> Map.put("preferredUsername", "admin")
|
||||
}}
|
||||
end)
|
||||
|
||||
actor = insert(:actor)
|
||||
data = File.read!("test/fixtures/mastodon-post-activity-private.json") |> Jason.decode!()
|
||||
data = Map.put(data, "to", [actor.url])
|
||||
|
||||
%Event{id: event_id, organizer_actor_id: organizer_actor_id} = event = insert(:event)
|
||||
|
||||
%Comment{url: reply_to_url, id: first_reply_comment_id} =
|
||||
insert(:comment, visibility: :private, event: event)
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("to", [actor.url])
|
||||
|> Map.put("inReplyTo", reply_to_url)
|
||||
|> Map.put("tag", [
|
||||
data["object"]["tag"]
|
||||
|> hd()
|
||||
|> Map.put("href", actor.url)
|
||||
|> Map.put("name", Actor.preferred_username_and_domain(actor))
|
||||
])
|
||||
|
||||
data = Map.put(data, "object", object)
|
||||
|
||||
{:ok, _activity,
|
||||
%Conversation{
|
||||
origin_comment: %Comment{visibility: :private, id: origin_comment_id},
|
||||
last_comment: %Comment{visibility: :private, id: _last_comment_id},
|
||||
participants: participants,
|
||||
event: %Event{id: ^event_id}
|
||||
}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert origin_comment_id == first_reply_comment_id
|
||||
participant_ids = participants |> Enum.map(& &1.id) |> MapSet.new()
|
||||
{:ok, admin} = Mobilizon.Actors.get_actor_by_url("https://framapiaf.org/users/admin")
|
||||
assert participant_ids == MapSet.new([actor.id, organizer_actor_id, admin.id])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
76
test/federation/activity_stream/converter/utils_test.exs
Normal file
76
test/federation/activity_stream/converter/utils_test.exs
Normal file
|
@ -0,0 +1,76 @@
|
|||
defmodule Mobilizon.Federation.ActivityStream.Converter.UtilsTest do
|
||||
@moduledoc """
|
||||
Module to test converting from EventMetadata to AS
|
||||
"""
|
||||
use Mobilizon.DataCase
|
||||
import Mobilizon.Factory
|
||||
alias Mobilizon.Federation.ActivityStream.Converter.Utils
|
||||
|
||||
describe "get_medias/1" do
|
||||
test "getting banner from Document attachment" do
|
||||
data =
|
||||
File.read!("test/fixtures/mobilizon-post-activity-media.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.get("object")
|
||||
|
||||
assert Utils.get_medias(data) ==
|
||||
{%{
|
||||
"blurhash" => "U5SY?Z00nOxu7ORP.8-pU^kVS#NGXyxbMxM{",
|
||||
"mediaType" => "image/png",
|
||||
"name" => nil,
|
||||
"type" => "Document",
|
||||
"url" => "https://mobilizon.fr/some-image"
|
||||
}, []}
|
||||
end
|
||||
|
||||
test "getting banner from image property" do
|
||||
data =
|
||||
File.read!("test/fixtures/mobilizon-post-activity-media-1.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.get("object")
|
||||
|
||||
assert Utils.get_medias(data) ==
|
||||
{%{
|
||||
"blurhash" => "U5SY?Z00nOxu7ORP.8-pU^kVS#NGXyxbMxM{",
|
||||
"mediaType" => "image/png",
|
||||
"name" => nil,
|
||||
"type" => "Image",
|
||||
"url" => "https://mobilizon.fr/some-image-1"
|
||||
},
|
||||
[
|
||||
%{
|
||||
"blurhash" => "U5SY?Z00nOxu7ORP.8-pU^kVS#NGXyxbMxM{",
|
||||
"mediaType" => "image/png",
|
||||
"name" => nil,
|
||||
"type" => "Document",
|
||||
"url" => "https://mobilizon.fr/some-image"
|
||||
}
|
||||
]}
|
||||
end
|
||||
|
||||
test "getting banner from attachment named \"Banner\"" do
|
||||
data =
|
||||
File.read!("test/fixtures/mobilizon-post-activity-media-2.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.get("object")
|
||||
|
||||
assert Utils.get_medias(data) ==
|
||||
{%{
|
||||
"blurhash" => "U5SY?Z00nOxu7ORP.8-pU^kVS#NGXyxbMxM{",
|
||||
"mediaType" => "image/png",
|
||||
"name" => "Banner",
|
||||
"type" => "Document",
|
||||
"url" => "https://mobilizon.fr/some-image-2"
|
||||
},
|
||||
[
|
||||
%{
|
||||
"blurhash" => "U5SY?Z00nOxu7ORP.8-pU^kVS#NGXyxbMxM{",
|
||||
"mediaType" => "image/png",
|
||||
"name" => nil,
|
||||
"type" => "Document",
|
||||
"url" => "https://mobilizon.fr/some-image-1"
|
||||
}
|
||||
]}
|
||||
end
|
||||
end
|
||||
end
|
106
test/fixtures/mobilizon-post-activity-media-1.json
vendored
Normal file
106
test/fixtures/mobilizon-post-activity-media-1.json
vendored
Normal file
|
@ -0,0 +1,106 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://litepub.social/litepub/context.jsonld",
|
||||
{
|
||||
"Hashtag": "as:Hashtag",
|
||||
"category": "sc:category",
|
||||
"ical": "http://www.w3.org/2002/12/cal/ical#",
|
||||
"joinMode": {
|
||||
"@id": "mz:joinMode",
|
||||
"@type": "mz:joinModeType"
|
||||
},
|
||||
"joinModeType": {
|
||||
"@id": "mz:joinModeType",
|
||||
"@type": "rdfs:Class"
|
||||
},
|
||||
"maximumAttendeeCapacity": "sc:maximumAttendeeCapacity",
|
||||
"mz": "https://joinmobilizon.org/ns#",
|
||||
"repliesModerationOption": {
|
||||
"@id": "mz:repliesModerationOption",
|
||||
"@type": "mz:repliesModerationOptionType"
|
||||
},
|
||||
"repliesModerationOptionType": {
|
||||
"@id": "mz:repliesModerationOptionType",
|
||||
"@type": "rdfs:Class"
|
||||
},
|
||||
"sc": "http://schema.org#",
|
||||
"uuid": "sc:identifier"
|
||||
}
|
||||
],
|
||||
"actor": "https://mobilizon.fr/@metacartes",
|
||||
"cc": [
|
||||
"https://framapiaf.org/users/admin/followers",
|
||||
"https://framapiaf.org/users/tcit"
|
||||
],
|
||||
"id": "https://mobilizon.fr/events/39a0c4a6-f2b6-41dc-bbe2-fc5bff76cc93/activity",
|
||||
"object": {
|
||||
"attachment": [
|
||||
{
|
||||
"href": "https://something.org",
|
||||
"mediaType": "text/html",
|
||||
"name": "Another link",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"href": "https://google.com",
|
||||
"mediaType": "text/html",
|
||||
"name": "Website",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"type": "Document",
|
||||
"mediaType": "image/png",
|
||||
"url": "https://mobilizon.fr/some-image",
|
||||
"name": null,
|
||||
"blurhash": "U5SY?Z00nOxu7ORP.8-pU^kVS#NGXyxbMxM{"
|
||||
}
|
||||
],
|
||||
"attributedTo": "https://mobilizon.fr/@metacartes",
|
||||
"startTime": "2018-02-12T14:08:20Z",
|
||||
"cc": [
|
||||
"https://framapiaf.org/users/admin/followers",
|
||||
"https://framapiaf.org/users/tcit"
|
||||
],
|
||||
"content": "<p><span class=\"h-card\"><a href=\"https://framapiaf.org/users/tcit\" class=\"u-url mention\">@<span>tcit</span></a></span></p>",
|
||||
"category": "TODO remove me",
|
||||
"id": "https://mobilizon.fr/events/39a0c4a6-f2b6-41dc-bbe2-fc5bff76cc93",
|
||||
"image": {
|
||||
"type": "Image",
|
||||
"mediaType": "image/png",
|
||||
"url": "https://mobilizon.fr/some-image-1",
|
||||
"name": null,
|
||||
"blurhash": "U5SY?Z00nOxu7ORP.8-pU^kVS#NGXyxbMxM{"
|
||||
},
|
||||
"inReplyTo": null,
|
||||
"location": {
|
||||
"type": "Place",
|
||||
"name": "Locaux de Framasoft",
|
||||
"id": "https://event1.tcit.fr/address/eeecc11d-0030-43e8-a897-6422876372jd",
|
||||
"address": {
|
||||
"type": "PostalAddress",
|
||||
"streetAddress": "10 Rue Jangot",
|
||||
"postalCode": "69007",
|
||||
"addressLocality": "Lyon",
|
||||
"addressRegion": "Auvergne Rhône Alpes",
|
||||
"addressCountry": "France"
|
||||
}
|
||||
},
|
||||
"name": "My first event",
|
||||
"published": "2018-02-12T14:08:20Z",
|
||||
"tag": [
|
||||
{
|
||||
"href": "https://framapiaf.org/users/tcit",
|
||||
"name": "@tcit@framapiaf.org",
|
||||
"type": "Mention"
|
||||
}
|
||||
],
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type": "Event",
|
||||
"url": "https://mobilizon.fr/events/39a0c4a6-f2b6-41dc-bbe2-fc5bff76cc93",
|
||||
"uuid": "109ccdfd-ee3e-46e1-a877-6c228763df0c"
|
||||
},
|
||||
"published": "2018-02-12T14:08:20Z",
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type": "Create"
|
||||
}
|
106
test/fixtures/mobilizon-post-activity-media-2.json
vendored
Normal file
106
test/fixtures/mobilizon-post-activity-media-2.json
vendored
Normal file
|
@ -0,0 +1,106 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://litepub.social/litepub/context.jsonld",
|
||||
{
|
||||
"Hashtag": "as:Hashtag",
|
||||
"category": "sc:category",
|
||||
"ical": "http://www.w3.org/2002/12/cal/ical#",
|
||||
"joinMode": {
|
||||
"@id": "mz:joinMode",
|
||||
"@type": "mz:joinModeType"
|
||||
},
|
||||
"joinModeType": {
|
||||
"@id": "mz:joinModeType",
|
||||
"@type": "rdfs:Class"
|
||||
},
|
||||
"maximumAttendeeCapacity": "sc:maximumAttendeeCapacity",
|
||||
"mz": "https://joinmobilizon.org/ns#",
|
||||
"repliesModerationOption": {
|
||||
"@id": "mz:repliesModerationOption",
|
||||
"@type": "mz:repliesModerationOptionType"
|
||||
},
|
||||
"repliesModerationOptionType": {
|
||||
"@id": "mz:repliesModerationOptionType",
|
||||
"@type": "rdfs:Class"
|
||||
},
|
||||
"sc": "http://schema.org#",
|
||||
"uuid": "sc:identifier"
|
||||
}
|
||||
],
|
||||
"actor": "https://mobilizon.fr/@metacartes",
|
||||
"cc": [
|
||||
"https://framapiaf.org/users/admin/followers",
|
||||
"https://framapiaf.org/users/tcit"
|
||||
],
|
||||
"id": "https://mobilizon.fr/events/39a0c4a6-f2b6-41dc-bbe2-fc5bff76cc93/activity",
|
||||
"object": {
|
||||
"attachment": [
|
||||
{
|
||||
"href": "https://something.org",
|
||||
"mediaType": "text/html",
|
||||
"name": "Another link",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"href": "https://google.com",
|
||||
"mediaType": "text/html",
|
||||
"name": "Website",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"type": "Document",
|
||||
"mediaType": "image/png",
|
||||
"url": "https://mobilizon.fr/some-image-1",
|
||||
"name": null,
|
||||
"blurhash": "U5SY?Z00nOxu7ORP.8-pU^kVS#NGXyxbMxM{"
|
||||
},
|
||||
{
|
||||
"type": "Document",
|
||||
"mediaType": "image/png",
|
||||
"url": "https://mobilizon.fr/some-image-2",
|
||||
"name": "Banner",
|
||||
"blurhash": "U5SY?Z00nOxu7ORP.8-pU^kVS#NGXyxbMxM{"
|
||||
}
|
||||
],
|
||||
"attributedTo": "https://mobilizon.fr/@metacartes",
|
||||
"startTime": "2018-02-12T14:08:20Z",
|
||||
"cc": [
|
||||
"https://framapiaf.org/users/admin/followers",
|
||||
"https://framapiaf.org/users/tcit"
|
||||
],
|
||||
"content": "<p><span class=\"h-card\"><a href=\"https://framapiaf.org/users/tcit\" class=\"u-url mention\">@<span>tcit</span></a></span></p>",
|
||||
"category": "TODO remove me",
|
||||
"id": "https://mobilizon.fr/events/39a0c4a6-f2b6-41dc-bbe2-fc5bff76cc93",
|
||||
"inReplyTo": null,
|
||||
"location": {
|
||||
"type": "Place",
|
||||
"name": "Locaux de Framasoft",
|
||||
"id": "https://event1.tcit.fr/address/eeecc11d-0030-43e8-a897-6422876372jd",
|
||||
"address": {
|
||||
"type": "PostalAddress",
|
||||
"streetAddress": "10 Rue Jangot",
|
||||
"postalCode": "69007",
|
||||
"addressLocality": "Lyon",
|
||||
"addressRegion": "Auvergne Rhône Alpes",
|
||||
"addressCountry": "France"
|
||||
}
|
||||
},
|
||||
"name": "My first event",
|
||||
"published": "2018-02-12T14:08:20Z",
|
||||
"tag": [
|
||||
{
|
||||
"href": "https://framapiaf.org/users/tcit",
|
||||
"name": "@tcit@framapiaf.org",
|
||||
"type": "Mention"
|
||||
}
|
||||
],
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type": "Event",
|
||||
"url": "https://mobilizon.fr/events/39a0c4a6-f2b6-41dc-bbe2-fc5bff76cc93",
|
||||
"uuid": "109ccdfd-ee3e-46e1-a877-6c228763df0c"
|
||||
},
|
||||
"published": "2018-02-12T14:08:20Z",
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type": "Create"
|
||||
}
|
99
test/fixtures/mobilizon-post-activity-media.json
vendored
Normal file
99
test/fixtures/mobilizon-post-activity-media.json
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://litepub.social/litepub/context.jsonld",
|
||||
{
|
||||
"Hashtag": "as:Hashtag",
|
||||
"category": "sc:category",
|
||||
"ical": "http://www.w3.org/2002/12/cal/ical#",
|
||||
"joinMode": {
|
||||
"@id": "mz:joinMode",
|
||||
"@type": "mz:joinModeType"
|
||||
},
|
||||
"joinModeType": {
|
||||
"@id": "mz:joinModeType",
|
||||
"@type": "rdfs:Class"
|
||||
},
|
||||
"maximumAttendeeCapacity": "sc:maximumAttendeeCapacity",
|
||||
"mz": "https://joinmobilizon.org/ns#",
|
||||
"repliesModerationOption": {
|
||||
"@id": "mz:repliesModerationOption",
|
||||
"@type": "mz:repliesModerationOptionType"
|
||||
},
|
||||
"repliesModerationOptionType": {
|
||||
"@id": "mz:repliesModerationOptionType",
|
||||
"@type": "rdfs:Class"
|
||||
},
|
||||
"sc": "http://schema.org#",
|
||||
"uuid": "sc:identifier"
|
||||
}
|
||||
],
|
||||
"actor": "https://mobilizon.fr/@metacartes",
|
||||
"cc": [
|
||||
"https://framapiaf.org/users/admin/followers",
|
||||
"https://framapiaf.org/users/tcit"
|
||||
],
|
||||
"id": "https://mobilizon.fr/events/39a0c4a6-f2b6-41dc-bbe2-fc5bff76cc93/activity",
|
||||
"object": {
|
||||
"attachment": [
|
||||
{
|
||||
"href": "https://something.org",
|
||||
"mediaType": "text/html",
|
||||
"name": "Another link",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"href": "https://google.com",
|
||||
"mediaType": "text/html",
|
||||
"name": "Website",
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"type": "Document",
|
||||
"mediaType": "image/png",
|
||||
"url": "https://mobilizon.fr/some-image",
|
||||
"name": null,
|
||||
"blurhash": "U5SY?Z00nOxu7ORP.8-pU^kVS#NGXyxbMxM{"
|
||||
}
|
||||
],
|
||||
"attributedTo": "https://mobilizon.fr/@metacartes",
|
||||
"startTime": "2018-02-12T14:08:20Z",
|
||||
"cc": [
|
||||
"https://framapiaf.org/users/admin/followers",
|
||||
"https://framapiaf.org/users/tcit"
|
||||
],
|
||||
"content": "<p><span class=\"h-card\"><a href=\"https://framapiaf.org/users/tcit\" class=\"u-url mention\">@<span>tcit</span></a></span></p>",
|
||||
"category": "TODO remove me",
|
||||
"id": "https://mobilizon.fr/events/39a0c4a6-f2b6-41dc-bbe2-fc5bff76cc93",
|
||||
"inReplyTo": null,
|
||||
"location": {
|
||||
"type": "Place",
|
||||
"name": "Locaux de Framasoft",
|
||||
"id": "https://event1.tcit.fr/address/eeecc11d-0030-43e8-a897-6422876372jd",
|
||||
"address": {
|
||||
"type": "PostalAddress",
|
||||
"streetAddress": "10 Rue Jangot",
|
||||
"postalCode": "69007",
|
||||
"addressLocality": "Lyon",
|
||||
"addressRegion": "Auvergne Rhône Alpes",
|
||||
"addressCountry": "France"
|
||||
}
|
||||
},
|
||||
"name": "My first event",
|
||||
"published": "2018-02-12T14:08:20Z",
|
||||
"tag": [
|
||||
{
|
||||
"href": "https://framapiaf.org/users/tcit",
|
||||
"name": "@tcit@framapiaf.org",
|
||||
"type": "Mention"
|
||||
}
|
||||
],
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type": "Event",
|
||||
"url": "https://mobilizon.fr/events/39a0c4a6-f2b6-41dc-bbe2-fc5bff76cc93",
|
||||
"uuid": "109ccdfd-ee3e-46e1-a877-6c228763df0c"
|
||||
},
|
||||
"published": "2018-02-12T14:08:20Z",
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type": "Create"
|
||||
}
|
|
@ -44,7 +44,8 @@ defmodule Mobilizon.GraphQL.Resolvers.ConversationTest do
|
|||
describe "Find conversations for event" do
|
||||
test "for a given event", %{conn: conn, user: user, actor: actor} do
|
||||
event = insert(:event, organizer_actor: actor)
|
||||
conversation = insert(:conversation, event: event)
|
||||
origin_comment = insert(:comment, actor: actor)
|
||||
conversation = insert(:conversation, event: event, origin_comment: origin_comment)
|
||||
another_comment = insert(:comment, origin_comment: conversation.origin_comment)
|
||||
|
||||
Discussions.update_comment(conversation.origin_comment, %{conversation_id: conversation.id})
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
defmodule Mobilizon.GraphQL.Resolvers.ParticipantTest do
|
||||
use Mobilizon.Web.ConnCase
|
||||
use Mobilizon.Tests.Helpers
|
||||
use Oban.Testing, repo: Mobilizon.Storage.Repo
|
||||
|
||||
alias Mobilizon.Config
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.{Actors, Config, Conversations, Events}
|
||||
alias Mobilizon.Events.{Event, EventParticipantStats, Participant}
|
||||
alias Mobilizon.GraphQL.AbsintheHelpers
|
||||
alias Mobilizon.Service.Workers.LegacyNotifierBuilder
|
||||
alias Mobilizon.Storage.Page
|
||||
|
||||
import Mobilizon.Factory
|
||||
|
@ -1381,4 +1383,393 @@ defmodule Mobilizon.GraphQL.Resolvers.ParticipantTest do
|
|||
assert_email_sent(to: @email)
|
||||
end
|
||||
end
|
||||
|
||||
describe "Send private messages to participants" do
|
||||
@send_event_private_message_mutation """
|
||||
mutation SendEventPrivateMessageMutation(
|
||||
$text: String!
|
||||
$actorId: ID!
|
||||
$eventId: ID!
|
||||
$roles: [ParticipantRoleEnum]
|
||||
$language: String
|
||||
) {
|
||||
sendEventPrivateMessage(
|
||||
text: $text
|
||||
actorId: $actorId
|
||||
eventId: $eventId
|
||||
roles: $roles
|
||||
language: $language
|
||||
) {
|
||||
id
|
||||
conversationParticipantId
|
||||
actor {
|
||||
id
|
||||
}
|
||||
lastComment {
|
||||
id
|
||||
text
|
||||
}
|
||||
originComment {
|
||||
id
|
||||
text
|
||||
}
|
||||
participants {
|
||||
id
|
||||
}
|
||||
event {
|
||||
id
|
||||
uuid
|
||||
title
|
||||
organizerActor {
|
||||
id
|
||||
}
|
||||
attributedTo {
|
||||
id
|
||||
}
|
||||
}
|
||||
unread
|
||||
insertedAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
setup %{conn: conn} do
|
||||
user = insert(:user)
|
||||
actor = insert(:actor, user: user, preferred_username: "test")
|
||||
|
||||
{:ok, conn: conn, actor: actor, user: user}
|
||||
end
|
||||
|
||||
test "Without being logged-in", %{conn: conn} do
|
||||
%Actor{id: actor_id} = insert(:actor)
|
||||
%Event{id: event_id} = insert(:event)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @send_event_private_message_mutation,
|
||||
variables: %{actorId: actor_id, eventId: event_id, text: "Hello dear participants"}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "You need to be logged in"
|
||||
end
|
||||
|
||||
test "With actor not allowed", %{conn: conn, actor: actor, user: user} do
|
||||
%Event{id: event_id} = insert(:event)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @send_event_private_message_mutation,
|
||||
variables: %{actorId: actor.id, eventId: event_id, text: "Hello dear participants"}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "You don't have permission to do this"
|
||||
end
|
||||
|
||||
test "With actor as event organizer", %{conn: conn, actor: actor, user: user} do
|
||||
%Event{id: event_id, title: event_title, uuid: event_uuid} =
|
||||
event = insert(:event, organizer_actor: actor)
|
||||
|
||||
%Participant{actor_id: participant_actor_id} = insert(:participant, event: event)
|
||||
%Participant{actor_id: participant_actor_id_2} = insert(:participant, event: event)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @send_event_private_message_mutation,
|
||||
variables: %{actorId: actor.id, eventId: event_id, text: "Hello dear participants"}
|
||||
)
|
||||
|
||||
assert res["errors"] == nil
|
||||
|
||||
assert res["data"]["sendEventPrivateMessage"]["lastComment"]["id"] ==
|
||||
res["data"]["sendEventPrivateMessage"]["originComment"]["id"]
|
||||
|
||||
assert res["data"]["sendEventPrivateMessage"]["lastComment"]["text"] ==
|
||||
"Hello dear participants"
|
||||
|
||||
participants_ids =
|
||||
Enum.map(res["data"]["sendEventPrivateMessage"]["participants"], fn participant ->
|
||||
String.to_integer(participant["id"])
|
||||
end)
|
||||
|
||||
assert length(participants_ids) == 3
|
||||
|
||||
assert MapSet.new(participants_ids) ==
|
||||
MapSet.new([actor.id, participant_actor_id, participant_actor_id_2])
|
||||
|
||||
assert res["data"]["sendEventPrivateMessage"]["actor"]["id"] == to_string(actor.id)
|
||||
conversation_id = res["data"]["sendEventPrivateMessage"]["id"]
|
||||
|
||||
all_conversation_participants_ids = Conversations.find_all_conversations_for_event(event_id)
|
||||
|
||||
notified_conversation_participant_ids =
|
||||
all_conversation_participants_ids
|
||||
|> Enum.filter(&(&1.actor_id != actor.id))
|
||||
|> Enum.map(&[&1.id, &1.actor_id])
|
||||
|
||||
Enum.each(notified_conversation_participant_ids, fn [pa_id, participant_actor_id] ->
|
||||
assert_enqueued(
|
||||
worker: LegacyNotifierBuilder,
|
||||
args: %{
|
||||
"author_id" => actor.id,
|
||||
"object_id" => to_string(conversation_id),
|
||||
"object_type" => "conversation",
|
||||
"op" => "legacy_notify",
|
||||
"subject" => "conversation_created",
|
||||
"subject_params" => %{
|
||||
"conversation_id" => String.to_integer(conversation_id),
|
||||
"conversation_participant_id" => pa_id,
|
||||
"conversation_text" => "Hello dear participants",
|
||||
"conversation_event_id" => event_id,
|
||||
"conversation_event_title" => event_title,
|
||||
"conversation_event_uuid" => event_uuid
|
||||
},
|
||||
"type" => "conversation",
|
||||
"participant" => %{
|
||||
"actor_id" => participant_actor_id,
|
||||
"id" => pa_id
|
||||
}
|
||||
}
|
||||
)
|
||||
end)
|
||||
|
||||
ignored_conversation_participant_id =
|
||||
all_conversation_participants_ids
|
||||
|> Enum.filter(&(&1.actor_id == actor.id))
|
||||
|> Enum.map(& &1.id)
|
||||
|
||||
refute_enqueued(
|
||||
worker: LegacyNotifierBuilder,
|
||||
args: %{
|
||||
"author_id" => actor.id,
|
||||
"object_id" => to_string(conversation_id),
|
||||
"object_type" => "conversation",
|
||||
"op" => "legacy_notify",
|
||||
"subject" => "conversation_created",
|
||||
"subject_params" => %{
|
||||
"conversation_id" => String.to_integer(conversation_id),
|
||||
"conversation_participant_id" => ignored_conversation_participant_id,
|
||||
"conversation_text" => "Hello dear participants",
|
||||
"conversation_event_id" => event_id,
|
||||
"conversation_event_title" => event_title,
|
||||
"conversation_event_uuid" => event_uuid
|
||||
},
|
||||
"type" => "conversation",
|
||||
"participant" => %{
|
||||
"actor_id" => actor.id,
|
||||
"id" => ignored_conversation_participant_id
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
test "With actor as event organizer with customized roles", %{
|
||||
conn: conn,
|
||||
actor: actor,
|
||||
user: user
|
||||
} do
|
||||
%Event{id: event_id, title: event_title, uuid: event_uuid} =
|
||||
event = insert(:event, organizer_actor: actor)
|
||||
|
||||
%Participant{actor_id: _participant_actor_id} = insert(:participant, event: event)
|
||||
|
||||
%Participant{actor_id: participant_actor_id_2} =
|
||||
insert(:participant, event: event, role: :not_approved)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @send_event_private_message_mutation,
|
||||
variables: %{
|
||||
actorId: actor.id,
|
||||
eventId: event_id,
|
||||
text: "Hello dear participants",
|
||||
roles: ["NOT_APPROVED"]
|
||||
}
|
||||
)
|
||||
|
||||
assert res["errors"] == nil
|
||||
|
||||
assert res["data"]["sendEventPrivateMessage"]["lastComment"]["id"] ==
|
||||
res["data"]["sendEventPrivateMessage"]["originComment"]["id"]
|
||||
|
||||
assert res["data"]["sendEventPrivateMessage"]["lastComment"]["text"] ==
|
||||
"Hello dear participants"
|
||||
|
||||
participants_ids =
|
||||
Enum.map(res["data"]["sendEventPrivateMessage"]["participants"], fn participant ->
|
||||
String.to_integer(participant["id"])
|
||||
end)
|
||||
|
||||
assert length(participants_ids) == 2
|
||||
|
||||
assert MapSet.new(participants_ids) ==
|
||||
MapSet.new([actor.id, participant_actor_id_2])
|
||||
|
||||
conversation_id = res["data"]["sendEventPrivateMessage"]["id"]
|
||||
|
||||
all_conversation_participants_ids = Conversations.find_all_conversations_for_event(event_id)
|
||||
|
||||
notified_conversation_participant_ids =
|
||||
all_conversation_participants_ids
|
||||
|> Enum.filter(&(&1.actor_id == participant_actor_id_2))
|
||||
|> Enum.map(&[&1.id, &1.actor_id])
|
||||
|
||||
Enum.each(notified_conversation_participant_ids, fn [pa_id, participant_actor_id] ->
|
||||
assert_enqueued(
|
||||
worker: LegacyNotifierBuilder,
|
||||
args: %{
|
||||
"author_id" => actor.id,
|
||||
"object_id" => to_string(conversation_id),
|
||||
"object_type" => "conversation",
|
||||
"op" => "legacy_notify",
|
||||
"subject" => "conversation_created",
|
||||
"subject_params" => %{
|
||||
"conversation_id" => String.to_integer(conversation_id),
|
||||
"conversation_participant_id" => pa_id,
|
||||
"conversation_text" => "Hello dear participants",
|
||||
"conversation_event_id" => event_id,
|
||||
"conversation_event_title" => event_title,
|
||||
"conversation_event_uuid" => event_uuid
|
||||
},
|
||||
"type" => "conversation",
|
||||
"participant" => %{
|
||||
"actor_id" => participant_actor_id,
|
||||
"id" => pa_id
|
||||
}
|
||||
}
|
||||
)
|
||||
end)
|
||||
|
||||
ignored_conversation_participant_id =
|
||||
all_conversation_participants_ids
|
||||
|> Enum.filter(&(&1.actor_id != participant_actor_id_2))
|
||||
|> Enum.map(&[&1.id, &1.actor_id])
|
||||
|
||||
Enum.each(ignored_conversation_participant_id, fn [pa_id, participant_actor_id] ->
|
||||
refute_enqueued(
|
||||
worker: LegacyNotifierBuilder,
|
||||
args: %{
|
||||
"author_id" => participant_actor_id,
|
||||
"object_id" => to_string(conversation_id),
|
||||
"object_type" => "conversation",
|
||||
"op" => "legacy_notify",
|
||||
"subject" => "conversation_created",
|
||||
"subject_params" => %{
|
||||
"conversation_id" => String.to_integer(conversation_id),
|
||||
"conversation_participant_id" => pa_id,
|
||||
"conversation_text" => "Hello dear participants",
|
||||
"conversation_event_id" => event_id,
|
||||
"conversation_event_title" => event_title,
|
||||
"conversation_event_uuid" => event_uuid
|
||||
},
|
||||
"type" => "conversation",
|
||||
"participant" => %{
|
||||
"actor_id" => participant_actor_id,
|
||||
"id" => pa_id
|
||||
}
|
||||
}
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
test "With actor as member of group event organizer", %{conn: conn, actor: actor, user: user} do
|
||||
%Actor{id: group_id} = group = insert(:group)
|
||||
insert(:member, parent: group, actor: actor, role: :moderator)
|
||||
%Event{id: event_id} = event = insert(:event, organizer_actor: actor, attributed_to: group)
|
||||
%Participant{actor_id: participant_actor_id} = insert(:participant, event: event)
|
||||
%Participant{actor_id: participant_actor_id_2} = insert(:participant, event: event)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @send_event_private_message_mutation,
|
||||
variables: %{actorId: group_id, eventId: event_id, text: "Hello dear participants"}
|
||||
)
|
||||
|
||||
assert res["errors"] == nil
|
||||
|
||||
participants_ids =
|
||||
Enum.map(res["data"]["sendEventPrivateMessage"]["participants"], fn participant ->
|
||||
String.to_integer(participant["id"])
|
||||
end)
|
||||
|
||||
assert MapSet.new(participants_ids) ==
|
||||
MapSet.new([group_id, participant_actor_id, participant_actor_id_2])
|
||||
|
||||
assert res["data"]["sendEventPrivateMessage"]["actor"]["id"] == to_string(group_id)
|
||||
end
|
||||
|
||||
test "With event not found", %{conn: conn, actor: actor, user: user} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @send_event_private_message_mutation,
|
||||
variables: %{actorId: actor.id, eventId: "5019438457", text: "Hello dear participants"}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] ==
|
||||
"Event not found"
|
||||
end
|
||||
|
||||
test "With no participants matching the audience", %{conn: conn, actor: actor, user: user} do
|
||||
%Event{id: event_id} = insert(:event, organizer_actor: actor)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @send_event_private_message_mutation,
|
||||
variables: %{actorId: actor.id, eventId: event_id, text: "Hello dear participants"}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] ==
|
||||
"There are no participants matching the audience you've selected."
|
||||
end
|
||||
end
|
||||
|
||||
test "With several anonymous participants", %{conn: conn, actor: actor, user: user} do
|
||||
%Event{id: event_id} =
|
||||
event = insert(:event, organizer_actor: actor)
|
||||
|
||||
{:ok, anonymous_actor} = Actors.get_or_create_internal_actor("anonymous")
|
||||
refute is_nil(anonymous_actor)
|
||||
|
||||
insert(:participant, event: event, actor: anonymous_actor, metadata: %{email: "anon@mou.se"})
|
||||
insert(:participant, event: event, actor: anonymous_actor, metadata: %{email: "other@mou.se"})
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @send_event_private_message_mutation,
|
||||
variables: %{actorId: actor.id, eventId: event_id, text: "Hello dear participants"}
|
||||
)
|
||||
|
||||
assert res["errors"] == nil
|
||||
|
||||
assert res["data"]["sendEventPrivateMessage"]["lastComment"]["id"] ==
|
||||
res["data"]["sendEventPrivateMessage"]["originComment"]["id"]
|
||||
|
||||
assert res["data"]["sendEventPrivateMessage"]["lastComment"]["text"] ==
|
||||
"Hello dear participants"
|
||||
|
||||
participants_ids =
|
||||
Enum.map(res["data"]["sendEventPrivateMessage"]["participants"], fn participant ->
|
||||
String.to_integer(participant["id"])
|
||||
end)
|
||||
|
||||
# Anonymous actor is only added once
|
||||
assert length(participants_ids) == 2
|
||||
|
||||
assert Enum.sort(participants_ids) == Enum.sort([actor.id, anonymous_actor.id])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,6 +7,7 @@ defmodule Mobilizon.Service.Activity.ConversationTest do
|
|||
alias Mobilizon.Conversations
|
||||
alias Mobilizon.Conversations.{Conversation, ConversationParticipant}
|
||||
alias Mobilizon.Discussions.Comment
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Service.Activity.Conversation, as: ConversationActivity
|
||||
alias Mobilizon.Service.Workers.LegacyNotifierBuilder
|
||||
alias Mobilizon.Users.User
|
||||
|
@ -15,16 +16,93 @@ defmodule Mobilizon.Service.Activity.ConversationTest do
|
|||
use Oban.Testing, repo: Mobilizon.Storage.Repo
|
||||
import Mobilizon.Factory
|
||||
|
||||
describe "handle conversation" do
|
||||
test "with participants" do
|
||||
describe "handle activity from event private announcement conversation" do
|
||||
test "when conversation initial comment author is not an organizer" do
|
||||
%User{} = user = insert(:user)
|
||||
%Actor{id: actor_id} = actor = insert(:actor, user: user)
|
||||
|
||||
%Conversation{
|
||||
id: conversation_id,
|
||||
last_comment: %Comment{actor_id: last_comment_actor_id}
|
||||
} =
|
||||
conversation = insert(:conversation, event: nil)
|
||||
%Actor{} = organizer_actor = insert(:actor)
|
||||
|
||||
%Event{} = event = insert(:event)
|
||||
|
||||
%Comment{} = comment = insert(:comment, actor: organizer_actor)
|
||||
|
||||
%Conversation{id: conversation_id} =
|
||||
conversation =
|
||||
insert(:conversation, event: event, last_comment: comment, origin_comment: comment)
|
||||
|
||||
%ConversationParticipant{id: conversation_participant_actor_id} =
|
||||
insert(:conversation_participant, actor: actor, conversation: conversation)
|
||||
|
||||
%ConversationParticipant{
|
||||
id: conversation_participant_id,
|
||||
actor: %Actor{id: conversation_other_participant_actor_id}
|
||||
} = insert(:conversation_participant, conversation: conversation)
|
||||
|
||||
conversation = Conversations.get_conversation(conversation_id)
|
||||
|
||||
assert {:ok, _} =
|
||||
ConversationActivity.insert_activity(conversation, subject: "conversation_created")
|
||||
|
||||
refute_enqueued(
|
||||
worker: LegacyNotifierBuilder,
|
||||
args: %{
|
||||
"author_id" => organizer_actor.id,
|
||||
"participant" => %{"actor_id" => actor_id, "id" => conversation_participant_actor_id},
|
||||
"object_id" => to_string(conversation_id),
|
||||
"object_type" => "conversation",
|
||||
"op" => "legacy_notify",
|
||||
"subject" => "conversation_created",
|
||||
"subject_params" => %{
|
||||
"conversation_id" => conversation_id,
|
||||
"conversation_participant_id" => conversation_participant_actor_id,
|
||||
"conversation_event_id" => event.id,
|
||||
"conversation_event_title" => event.title,
|
||||
"conversation_event_uuid" => event.uuid
|
||||
},
|
||||
"type" => "conversation"
|
||||
}
|
||||
)
|
||||
|
||||
refute_enqueued(
|
||||
worker: LegacyNotifierBuilder,
|
||||
args: %{
|
||||
"author_id" => organizer_actor.id,
|
||||
"participant" => %{
|
||||
"actor_id" => conversation_other_participant_actor_id,
|
||||
"id" => conversation_participant_id
|
||||
},
|
||||
"object_id" => to_string(conversation_id),
|
||||
"object_type" => "conversation",
|
||||
"op" => "legacy_notify",
|
||||
"subject" => "conversation_created",
|
||||
"subject_params" => %{
|
||||
"conversation_id" => conversation_id,
|
||||
"conversation_participant_id" => conversation_participant_id,
|
||||
"conversation_event_id" => event.id,
|
||||
"conversation_event_title" => event.title,
|
||||
"conversation_event_uuid" => event.uuid
|
||||
},
|
||||
"type" => "conversation"
|
||||
}
|
||||
)
|
||||
|
||||
assert [] = all_enqueued()
|
||||
end
|
||||
|
||||
test "an author who is the event organizer" do
|
||||
%User{} = user = insert(:user)
|
||||
%Actor{id: actor_id} = actor = insert(:actor, user: user)
|
||||
|
||||
%Actor{} = organizer_actor = insert(:actor)
|
||||
|
||||
%Event{} = event = insert(:event, organizer_actor: organizer_actor)
|
||||
|
||||
%Comment{} = comment = insert(:comment, actor: organizer_actor)
|
||||
|
||||
%Conversation{id: conversation_id} =
|
||||
conversation =
|
||||
insert(:conversation, event: event, last_comment: comment, origin_comment: comment)
|
||||
|
||||
%ConversationParticipant{id: conversation_participant_actor_id} =
|
||||
insert(:conversation_participant, actor: actor, conversation: conversation)
|
||||
|
@ -42,7 +120,7 @@ defmodule Mobilizon.Service.Activity.ConversationTest do
|
|||
assert_enqueued(
|
||||
worker: LegacyNotifierBuilder,
|
||||
args: %{
|
||||
"author_id" => last_comment_actor_id,
|
||||
"author_id" => organizer_actor.id,
|
||||
"participant" => %{"actor_id" => actor_id, "id" => conversation_participant_actor_id},
|
||||
"object_id" => to_string(conversation_id),
|
||||
"object_type" => "conversation",
|
||||
|
@ -50,7 +128,10 @@ defmodule Mobilizon.Service.Activity.ConversationTest do
|
|||
"subject" => "conversation_created",
|
||||
"subject_params" => %{
|
||||
"conversation_id" => conversation_id,
|
||||
"conversation_participant_id" => conversation_participant_actor_id
|
||||
"conversation_participant_id" => conversation_participant_actor_id,
|
||||
"conversation_event_id" => event.id,
|
||||
"conversation_event_title" => event.title,
|
||||
"conversation_event_uuid" => event.uuid
|
||||
},
|
||||
"type" => "conversation"
|
||||
}
|
||||
|
@ -59,7 +140,7 @@ defmodule Mobilizon.Service.Activity.ConversationTest do
|
|||
assert_enqueued(
|
||||
worker: LegacyNotifierBuilder,
|
||||
args: %{
|
||||
"author_id" => last_comment_actor_id,
|
||||
"author_id" => organizer_actor.id,
|
||||
"participant" => %{
|
||||
"actor_id" => conversation_other_participant_actor_id,
|
||||
"id" => conversation_participant_id
|
||||
|
@ -70,7 +151,81 @@ defmodule Mobilizon.Service.Activity.ConversationTest do
|
|||
"subject" => "conversation_created",
|
||||
"subject_params" => %{
|
||||
"conversation_id" => conversation_id,
|
||||
"conversation_participant_id" => conversation_participant_id
|
||||
"conversation_participant_id" => conversation_participant_id,
|
||||
"conversation_event_id" => event.id,
|
||||
"conversation_event_title" => event.title,
|
||||
"conversation_event_uuid" => event.uuid
|
||||
},
|
||||
"type" => "conversation"
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
test "an author who is member of the event organizer group" do
|
||||
%User{} = user = insert(:user)
|
||||
%Actor{id: actor_id} = actor = insert(:actor, user: user)
|
||||
|
||||
%Actor{} = organizer_group = insert(:group)
|
||||
|
||||
%Event{} = event = insert(:event, attributed_to: organizer_group)
|
||||
|
||||
%Comment{} = comment = insert(:comment, actor: organizer_group)
|
||||
|
||||
%Conversation{id: conversation_id} =
|
||||
conversation =
|
||||
insert(:conversation, event: event, last_comment: comment, origin_comment: comment)
|
||||
|
||||
%ConversationParticipant{id: conversation_participant_actor_id} =
|
||||
insert(:conversation_participant, actor: actor, conversation: conversation)
|
||||
|
||||
%ConversationParticipant{
|
||||
id: conversation_participant_id,
|
||||
actor: %Actor{id: conversation_other_participant_actor_id}
|
||||
} = insert(:conversation_participant, conversation: conversation)
|
||||
|
||||
conversation = Conversations.get_conversation(conversation_id)
|
||||
|
||||
assert {:ok, _} =
|
||||
ConversationActivity.insert_activity(conversation, subject: "conversation_created")
|
||||
|
||||
assert_enqueued(
|
||||
worker: LegacyNotifierBuilder,
|
||||
args: %{
|
||||
"author_id" => organizer_group.id,
|
||||
"participant" => %{"actor_id" => actor_id, "id" => conversation_participant_actor_id},
|
||||
"object_id" => to_string(conversation_id),
|
||||
"object_type" => "conversation",
|
||||
"op" => "legacy_notify",
|
||||
"subject" => "conversation_created",
|
||||
"subject_params" => %{
|
||||
"conversation_id" => conversation_id,
|
||||
"conversation_participant_id" => conversation_participant_actor_id,
|
||||
"conversation_event_id" => event.id,
|
||||
"conversation_event_title" => event.title,
|
||||
"conversation_event_uuid" => event.uuid
|
||||
},
|
||||
"type" => "conversation"
|
||||
}
|
||||
)
|
||||
|
||||
assert_enqueued(
|
||||
worker: LegacyNotifierBuilder,
|
||||
args: %{
|
||||
"author_id" => organizer_group.id,
|
||||
"participant" => %{
|
||||
"actor_id" => conversation_other_participant_actor_id,
|
||||
"id" => conversation_participant_id
|
||||
},
|
||||
"object_id" => to_string(conversation_id),
|
||||
"object_type" => "conversation",
|
||||
"op" => "legacy_notify",
|
||||
"subject" => "conversation_created",
|
||||
"subject_params" => %{
|
||||
"conversation_id" => conversation_id,
|
||||
"conversation_participant_id" => conversation_participant_id,
|
||||
"conversation_event_id" => event.id,
|
||||
"conversation_event_title" => event.title,
|
||||
"conversation_event_uuid" => event.uuid
|
||||
},
|
||||
"type" => "conversation"
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ defmodule Mobilizon.Service.Metadata.InstanceTest do
|
|||
|
||||
assert Instance.build_tags() |> Utils.stringify_tags() ==
|
||||
"""
|
||||
<title>#{title}</title><meta content="#{description}" name="description"><meta content="#{title}" property="og:title"><meta content="#{Endpoint.url()}" property="og:url"><meta content="#{description}" property="og:description"><meta content="website" property="og:type"><script type="application/ld+json">{"@context":"http://schema.org","@type":"WebSite","name":"#{title}","potentialAction":{"@type":"SearchAction","query-input":"required name=search_term","target":"#{Endpoint.url()}/search?term={search_term}"},"url":"#{Endpoint.url()}"}</script>
|
||||
<title>#{title}</title><meta content="#{description}" name="description"><meta content="#{title}" property="og:title"><meta content="#{Endpoint.url()}" property="og:url"><meta content="#{description}" property="og:description"><meta content="website" property="og:type"><script type="application/ld+json">{"@context":"http://schema.org","@type":"WebSite","name":"#{title}","potentialAction":{"@type":"SearchAction","query-input":"required name=search_term","target":"#{Endpoint.url()}/search?term={search_term}"},"url":"#{Endpoint.url()}"}</script>\n<link href=\"#{Endpoint.url()}/feed/instance/atom\" rel=\"alternate\" title=\"Test instance's feed\" type=\"application/atom+xml\"><link href=\"#{Endpoint.url()}/feed/instance/ics\" rel=\"alternate\" title=\"Test instance's feed\" type=\"text/calendar\">\
|
||||
"""
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@ defmodule Mobilizon.Service.Workers.LegacyNotifierBuilderTest do
|
|||
"""
|
||||
|
||||
alias Mobilizon.Activities.Activity
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Discussions.{Comment, Discussion}
|
||||
alias Mobilizon.Events.Event
|
||||
|
@ -15,6 +16,7 @@ defmodule Mobilizon.Service.Workers.LegacyNotifierBuilderTest do
|
|||
use Mobilizon.Tests.Helpers
|
||||
import Mox
|
||||
import Mobilizon.Factory
|
||||
import Mobilizon.Tests.SwooshAssertions
|
||||
|
||||
setup_all do
|
||||
Mox.defmock(NotifierMock, for: Mobilizon.Service.Notifier)
|
||||
|
@ -42,7 +44,7 @@ defmodule Mobilizon.Service.Workers.LegacyNotifierBuilderTest do
|
|||
"op" => "legacy_notify"
|
||||
}
|
||||
|
||||
@announcement %{
|
||||
@public_announcement %{
|
||||
"type" => "comment",
|
||||
"subject" => "participation_event_comment",
|
||||
"object_type" => "comment",
|
||||
|
@ -50,6 +52,14 @@ defmodule Mobilizon.Service.Workers.LegacyNotifierBuilderTest do
|
|||
"op" => "legacy_notify"
|
||||
}
|
||||
|
||||
@private_announcement %{
|
||||
"type" => "conversation",
|
||||
"subject" => "conversation_created",
|
||||
"object_type" => "conversation",
|
||||
"inserted_at" => DateTime.utc_now(),
|
||||
"op" => "legacy_notify"
|
||||
}
|
||||
|
||||
setup :verify_on_exit!
|
||||
|
||||
describe "Generates a comment mention notification " do
|
||||
|
@ -138,7 +148,7 @@ defmodule Mobilizon.Service.Workers.LegacyNotifierBuilderTest do
|
|||
%Comment{id: comment_id} = insert(:comment, event: event, actor: actor)
|
||||
|
||||
args =
|
||||
Map.merge(@announcement, %{
|
||||
Map.merge(@public_announcement, %{
|
||||
"subject_params" => %{
|
||||
"event_uuid" => uuid,
|
||||
"event_title" => title,
|
||||
|
@ -177,7 +187,7 @@ defmodule Mobilizon.Service.Workers.LegacyNotifierBuilderTest do
|
|||
insert(:participant, event: event, actor: actor2)
|
||||
|
||||
args =
|
||||
Map.merge(@announcement, %{
|
||||
Map.merge(@public_announcement, %{
|
||||
"subject_params" => %{
|
||||
"event_uuid" => uuid,
|
||||
"event_title" => title,
|
||||
|
@ -334,4 +344,91 @@ defmodule Mobilizon.Service.Workers.LegacyNotifierBuilderTest do
|
|||
assert :ok == LegacyNotifierBuilder.perform(%Oban.Job{args: args})
|
||||
end
|
||||
end
|
||||
|
||||
describe "Generates a private event announcement notification" do
|
||||
test "sends emails to target users" do
|
||||
user1 = insert(:user, email: "user1@do.main")
|
||||
actor1 = insert(:actor, user: user1)
|
||||
user2 = insert(:user, email: "user2@do.main")
|
||||
actor2 = insert(:actor, user: user2)
|
||||
event = insert(:event)
|
||||
comment = insert(:comment, actor: actor2, visibility: :private)
|
||||
|
||||
conversation =
|
||||
insert(:conversation, event: event, last_comment: comment, origin_comment: comment)
|
||||
|
||||
conversation_participant =
|
||||
insert(:conversation_participant, conversation: conversation, actor: actor1)
|
||||
|
||||
args =
|
||||
Map.merge(@private_announcement, %{
|
||||
"subject_params" => %{
|
||||
"conversation_id" => conversation.id,
|
||||
"conversation_participant_id" => conversation_participant.id,
|
||||
"conversation_text" => conversation.last_comment.text,
|
||||
"conversation_event_id" => event.id,
|
||||
"conversation_event_title" => event.title,
|
||||
"conversation_event_uuid" => event.uuid
|
||||
},
|
||||
"author_id" => conversation.last_comment.actor.id,
|
||||
"object_id" => conversation.last_comment.id,
|
||||
"participant" => %{
|
||||
"actor_id" => actor1.id,
|
||||
"id" => conversation_participant.id
|
||||
}
|
||||
})
|
||||
|
||||
LegacyNotifierBuilder.perform(%Oban.Job{args: args})
|
||||
|
||||
assert_email_sent(%Swoosh.Email{to: [{"", "user1@do.main"}]})
|
||||
refute_email_sent(%Swoosh.Email{to: [{"", "user2@do.main"}]})
|
||||
refute_email_sent(%Swoosh.Email{to: [{"", "user1@do.main"}]})
|
||||
end
|
||||
|
||||
test "sends emails to anonymous participants" do
|
||||
{:ok, anonymous_actor} = Actors.get_or_create_internal_actor("anonymous")
|
||||
refute is_nil(anonymous_actor)
|
||||
user2 = insert(:user, email: "user2@do.main")
|
||||
actor2 = insert(:actor, user: user2)
|
||||
event = insert(:event)
|
||||
comment = insert(:comment, actor: actor2, visibility: :private)
|
||||
|
||||
insert(:participant,
|
||||
event: event,
|
||||
actor: anonymous_actor,
|
||||
metadata: %{email: "anon@mou.se"}
|
||||
)
|
||||
|
||||
conversation =
|
||||
insert(:conversation, event: event, last_comment: comment, origin_comment: comment)
|
||||
|
||||
conversation_participant =
|
||||
insert(:conversation_participant, conversation: conversation, actor: anonymous_actor)
|
||||
|
||||
args =
|
||||
Map.merge(@private_announcement, %{
|
||||
"subject_params" => %{
|
||||
"conversation_id" => conversation.id,
|
||||
"conversation_participant_id" => conversation_participant.id,
|
||||
"conversation_text" => conversation.last_comment.text,
|
||||
"conversation_event_id" => event.id,
|
||||
"conversation_event_title" => event.title,
|
||||
"conversation_event_uuid" => event.uuid
|
||||
},
|
||||
"author_id" => conversation.last_comment.actor.id,
|
||||
"object_id" => conversation.last_comment.id,
|
||||
"participant" => %{
|
||||
"actor_id" => anonymous_actor.id,
|
||||
"id" => conversation_participant.id
|
||||
}
|
||||
})
|
||||
|
||||
LegacyNotifierBuilder.perform(%Oban.Job{args: args})
|
||||
|
||||
assert_email_sending(%Swoosh.Email{to: [{"", "anon@mou.se"}]}, 10_000)
|
||||
refute_email_sent(%Swoosh.Email{to: [{"", "user2@do.main"}]})
|
||||
# Because of timeouts, can't do that currently
|
||||
# refute_email_sent(%Swoosh.Email{to: [{"", "anon@mou.se"}]})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
91
test/support/swoosh_assertions.ex
Normal file
91
test/support/swoosh_assertions.ex
Normal file
|
@ -0,0 +1,91 @@
|
|||
# The following module is taken from this issue
|
||||
# https://github.com/swoosh/swoosh/issues/488#issuecomment-1671224765
|
||||
|
||||
defmodule Mobilizon.Tests.SwooshAssertions do
|
||||
@moduledoc ~S"""
|
||||
Assertions for emails.
|
||||
|
||||
The assertions provided by this module work by pattern matching
|
||||
against all emails received by the test process against the
|
||||
`Swoosh.Email` struct. For example:
|
||||
|
||||
assert_email_sent %{subject: "You got a message"}
|
||||
|
||||
If you want to be additionally explicit, you might:
|
||||
|
||||
assert_email_sent %Swoosh.Email{subject: "You got a message"}
|
||||
|
||||
If emails are being sent concurrently, you can use `assert_email_sending/2`:
|
||||
|
||||
assert_email_sending %{subject: "You got a message"}
|
||||
|
||||
Both functions will return the matched email if the assertion succeeds.
|
||||
You can then perform further matches on it:
|
||||
|
||||
email = assert_email_sent %Swoosh.Email{subject: "You got a message"}
|
||||
assert email.from == {"MyApp", "no-reply@example.com"}
|
||||
|
||||
Using pattern matching imposes two limitations. The first one is that you
|
||||
must match precisely the Swoosh.Email structure. For example, the following
|
||||
will not work:
|
||||
|
||||
assert_email_sent %{to: "foobar@example.com"}
|
||||
|
||||
That's because `Swoosh.Email` keeps the field as a list. This will work:
|
||||
|
||||
assert_email_sent %{to: [{"FooBar", "foobar@example.com"}]}
|
||||
|
||||
You are also not allowed to have interpolations. For example, the following
|
||||
will not work:
|
||||
|
||||
assert_email_sent %{
|
||||
subject: "You have been invited to #{org.name}",
|
||||
to: [{user.name, user.email}]
|
||||
}
|
||||
|
||||
However, you can rely on pattern matching and rewrite it as:
|
||||
|
||||
email = assert_email_sent %{subject: "You have been invited to " <> org_name}
|
||||
assert org_name == org.name
|
||||
assert email.to == [{user.name, user.email}]
|
||||
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Matches an email has been sent.
|
||||
|
||||
See moduledoc for more information.
|
||||
"""
|
||||
defmacro assert_email_sent(pattern) do
|
||||
quote do
|
||||
{:email, email} = assert_received({:email, unquote(pattern)})
|
||||
email
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Matches an email is sending (within a timeout).
|
||||
|
||||
See moduledoc for more information.
|
||||
"""
|
||||
defmacro assert_email_sending(
|
||||
pattern,
|
||||
timeout \\ Application.fetch_env!(:ex_unit, :assert_receive_timeout)
|
||||
) do
|
||||
quote do
|
||||
{:email, email} = assert_receive({:email, unquote(pattern)}, unquote(timeout))
|
||||
email
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Refutes an email matching pattern has been sent.
|
||||
|
||||
The opposite of `assert_email_sent`.
|
||||
"""
|
||||
defmacro refute_email_sent(pattern) do
|
||||
quote do
|
||||
refute_received({:email, unquote(pattern)})
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
// vetur.config.js
|
||||
/** @type {import('vls').VeturConfig} */
|
||||
module.exports = {
|
||||
projects: ["./js"],
|
||||
};
|
Loading…
Reference in a new issue