+
{{ $t('Add to my calendar') }}
@@ -911,20 +912,21 @@ export default class Event extends EventMixin {
h3 {
margin-right: 0;
- margin-left: auto;
}
}
.add-to-calendar {
- background-repeat: no-repeat;
- background-size: 400px;
- background-position: 10% 50%;
- background-image: url('../../assets/undraw_events.svg');
- position: relative;
+ display: flex;
+
h3 {
+ margin-left: 0;
cursor: pointer;
}
+ img {
+ max-width: 400px;
+ }
+
&::before {
content:"";
background: #B3B3B2;
diff --git a/lib/mobilizon/addresses/address.ex b/lib/mobilizon/addresses/address.ex
index 63a455952..c7c6453e1 100644
--- a/lib/mobilizon/addresses/address.ex
+++ b/lib/mobilizon/addresses/address.ex
@@ -69,4 +69,20 @@ defmodule Mobilizon.Addresses.Address do
put_change(changeset, :url, url)
end
+
+ def coords(nil), do: nil
+
+ def coords(%__MODULE__{} = address) do
+ with %Geo.Point{coordinates: {latitude, longitude}, srid: 4326} <- address.geom do
+ {latitude, longitude}
+ end
+ end
+
+ def representation(nil), do: nil
+
+ def representation(%__MODULE__{} = address) do
+ "#{address.street} #{address.postal_code} #{address.locality} #{address.region} #{
+ address.country
+ }"
+ end
end
diff --git a/lib/mobilizon/events/event.ex b/lib/mobilizon/events/event.ex
index fcd1ea745..2978e785a 100644
--- a/lib/mobilizon/events/event.ex
+++ b/lib/mobilizon/events/event.ex
@@ -187,8 +187,9 @@ defmodule Mobilizon.Events.Event do
# In case the provided addresses is an existing one
@spec put_address(Changeset.t(), map) :: Changeset.t()
- defp put_address(%Changeset{} = changeset, %{physical_address: %{id: id} = _physical_address}) do
- case Addresses.get_address!(id) do
+ defp put_address(%Changeset{} = changeset, %{physical_address: %{id: id} = _physical_address})
+ when not is_nil(id) do
+ case Addresses.get_address(id) do
%Address{} = address ->
put_assoc(changeset, :physical_address, address)
diff --git a/lib/service/export/icalendar.ex b/lib/service/export/icalendar.ex
index 2d65e519e..32ec1625e 100644
--- a/lib/service/export/icalendar.ex
+++ b/lib/service/export/icalendar.ex
@@ -6,6 +6,7 @@ defmodule Mobilizon.Service.Export.ICalendar do
alias Mobilizon.{Actors, Events, Users}
alias Mobilizon.Actors.Actor
alias Mobilizon.Events.{Event, FeedToken}
+ alias Mobilizon.Addresses.Address
alias Mobilizon.Users.User
@doc """
@@ -31,7 +32,10 @@ defmodule Mobilizon.Service.Export.ICalendar do
dtend: event.ends_on,
description: HtmlSanitizeEx.strip_tags(event.description),
uid: event.uuid,
- categories: event.tags |> Enum.map(& &1.slug)
+ url: event.url,
+ geo: Address.coords(event.physical_address),
+ location: Address.representation(event.physical_address),
+ categories: event.tags |> Enum.map(& &1.title)
}
end
diff --git a/test/mobilizon/service/export/icalendar_test.exs b/test/mobilizon/service/export/icalendar_test.exs
new file mode 100644
index 000000000..aae737b63
--- /dev/null
+++ b/test/mobilizon/service/export/icalendar_test.exs
@@ -0,0 +1,37 @@
+defmodule Mobilizon.Service.ICalendarTest do
+ alias Mobilizon.Service.Export.ICalendar, as: ICalendarService
+ alias Mobilizon.Events.Event
+ alias Mobilizon.Addresses.Address
+ alias ICalendar.Value
+ use Mobilizon.DataCase
+
+ import Mobilizon.Factory
+
+ describe "export an event to ics" do
+ test "export basic infos" do
+ %Event{} = event = insert(:event)
+
+ ics = """
+ BEGIN:VCALENDAR
+ CALSCALE:GREGORIAN
+ VERSION:2.0
+ PRODID:-//ICalendar//Mobilizon//EN
+ BEGIN:VEVENT
+ CATEGORIES:#{event.tags |> Enum.map(& &1.title) |> Enum.join(",")}
+ DESCRIPTION:Ceci est une description avec une première phrase assez longue\\,\\n puis sur une seconde ligne
+ DTEND:#{Value.to_ics(event.ends_on)}
+ DTSTAMP:#{Value.to_ics(event.publish_at)}
+ DTSTART:#{Value.to_ics(event.begins_on)}
+ GEO:#{event.physical_address |> Address.coords() |> Tuple.to_list() |> Enum.join(";")}
+ LOCATION:#{Address.representation(event.physical_address)}
+ SUMMARY:#{event.title}
+ UID:#{event.uuid}
+ URL:#{event.url}
+ END:VEVENT
+ END:VCALENDAR
+ """
+
+ assert {:ok, ics} == ICalendarService.export_public_event(event)
+ end
+ end
+end
diff --git a/test/mobilizon_web/controllers/feed_controller_test.exs b/test/mobilizon_web/controllers/feed_controller_test.exs
index d793586b3..a9d4423bd 100644
--- a/test/mobilizon_web/controllers/feed_controller_test.exs
+++ b/test/mobilizon_web/controllers/feed_controller_test.exs
@@ -36,8 +36,10 @@ defmodule MobilizonWeb.FeedControllerTest do
assert entry.title in [event1.title, event2.title]
end)
- assert entry1.categories == [tag2.slug, tag1.slug]
- assert entry2.categories == [tag1.slug]
+ # It seems categories takes term instead of Label
+ #
+ assert entry1.categories == [tag2.title, tag1.title] |> Enum.map(&String.downcase/1)
+ assert entry2.categories == [tag1.title] |> Enum.map(&String.downcase/1)
end
test "it returns a 404 for the actor's public events Atom feed if the actor is not publicly visible",
@@ -112,8 +114,8 @@ defmodule MobilizonWeb.FeedControllerTest do
assert entry.summary in [event1.title, event2.title]
end)
- assert entry1.categories == [tag1.slug]
- assert entry2.categories == [tag1.slug, tag2.slug]
+ assert entry1.categories == [tag1.title]
+ assert entry2.categories == [tag1.title, tag2.title]
end
test "it returns a 404 page for the actor's public events iCal feed with an actor not publicly visible",
@@ -183,7 +185,7 @@ defmodule MobilizonWeb.FeedControllerTest do
assert entry1.summary == event1.title
- assert entry1.categories == [tag1.slug, tag2.slug]
+ assert entry1.categories == [tag1.title, tag2.title]
end
end
@@ -325,7 +327,7 @@ defmodule MobilizonWeb.FeedControllerTest do
[entry1] = ExIcal.parse(conn.resp_body)
assert entry1.summary == event1.title
- assert entry1.categories == event1.tags |> Enum.map(& &1.slug)
+ assert entry1.categories == event1.tags |> Enum.map(& &1.title)
end
test "it returns 404 for an not existing feed", %{conn: conn} do
diff --git a/test/support/factory.ex b/test/support/factory.ex
index bbb0d2250..336eccdf2 100644
--- a/test/support/factory.ex
+++ b/test/support/factory.ex
@@ -124,6 +124,7 @@ defmodule Mobilizon.Factory do
visibility: :public,
tags: build_list(3, :tag),
mentions: [],
+ publish_at: DateTime.utc_now(),
url: Routes.page_url(Endpoint, :event, uuid),
picture: insert(:picture),
uuid: uuid,