From ed7e6e4d4b6f0c0a31bdeca8cf971819c2d746d9 Mon Sep 17 00:00:00 2001
From: Thomas Citharel <tcit@tcit.fr>
Date: Mon, 22 Nov 2021 18:31:13 +0100
Subject: [PATCH 1/7] Fix extra padding on event truncated title

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
---
 js/src/components/Event/EventCard.vue | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/js/src/components/Event/EventCard.vue b/js/src/components/Event/EventCard.vue
index 541b1c4a6..0d2e83370 100644
--- a/js/src/components/Event/EventCard.vue
+++ b/js/src/components/Event/EventCard.vue
@@ -248,10 +248,13 @@ a.card {
       -webkit-line-clamp: 3;
       -webkit-box-orient: vertical;
       overflow: hidden;
-      padding-bottom: 8px;
       font-weight: bold;
     }
 
+    .content-end {
+      padding-top: 8px;
+    }
+
     .event-subtitle {
       font-size: 0.85rem;
     }

From 377b83e02d9832fb335e63f68e071952ccf06ea5 Mon Sep 17 00:00:00 2001
From: Thomas Citharel <tcit@tcit.fr>
Date: Mon, 22 Nov 2021 18:43:59 +0100
Subject: [PATCH 2/7] Fix export being outputted in the wrong directory in
 release mode

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
---
 config/config.exs                         |  1 +
 config/dev.exs                            |  2 ++
 config/test.exs                           |  2 ++
 lib/service/export/participants/common.ex | 11 ++++++++++-
 lib/service/export/participants/csv.ex    | 18 +++++++++++-------
 lib/service/export/participants/ods.ex    | 15 ++++++++++-----
 lib/service/export/participants/pdf.ex    | 15 ++++++++++-----
 lib/web/controllers/export_controller.ex  |  4 ++--
 8 files changed, 48 insertions(+), 20 deletions(-)

diff --git a/config/config.exs b/config/config.exs
index 17674049a..abdf22eec 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -329,6 +329,7 @@ config :mobilizon, Mobilizon.Service.Notifier.Email, enabled: true
 config :mobilizon, Mobilizon.Service.Notifier.Push, enabled: true
 
 config :mobilizon, :exports,
+  path: "/var/lib/mobilizon/uploads/exports",
   formats: [
     Mobilizon.Service.Export.Participants.CSV
   ]
diff --git a/config/dev.exs b/config/dev.exs
index d7a28a2ac..c78500a99 100644
--- a/config/dev.exs
+++ b/config/dev.exs
@@ -94,6 +94,8 @@ config :mobilizon, Mobilizon.Web.Auth.Guardian,
 
 config :mobilizon, Mobilizon.Web.Upload.Uploader.Local, uploads: "uploads"
 
+config :mobilizon, :exports, path: "uploads/exports"
+
 config :tz_world, data_dir: "_build/dev/lib/tz_world/priv"
 
 config :mobilizon, :anonymous,
diff --git a/config/test.exs b/config/test.exs
index c6338b88e..d0a4afa0a 100644
--- a/config/test.exs
+++ b/config/test.exs
@@ -60,6 +60,8 @@ config :mobilizon, Mobilizon.Web.Upload, filters: [], link_name: false
 
 config :mobilizon, Mobilizon.Web.Upload.Uploader.Local, uploads: "test/uploads"
 
+config :mobilizon, :exports, path: "test/uploads/exports"
+
 config :tz_world, data_dir: "_build/test/lib/tz_world/priv"
 
 config :tesla, Mobilizon.Service.HTTP.ActivityPub,
diff --git a/lib/service/export/participants/common.ex b/lib/service/export/participants/common.ex
index b1292b9c7..3512d0dc2 100644
--- a/lib/service/export/participants/common.ex
+++ b/lib/service/export/participants/common.ex
@@ -4,9 +4,9 @@ defmodule Mobilizon.Service.Export.Participants.Common do
   """
 
   alias Mobilizon.Actors.Actor
+  alias Mobilizon.{Config, Export}
   alias Mobilizon.Events.Participant
   alias Mobilizon.Events.Participant.Metadata
-  alias Mobilizon.Export
   alias Mobilizon.Storage.Repo
   import Mobilizon.Web.Gettext, only: [gettext: 1]
 
@@ -117,4 +117,13 @@ defmodule Mobilizon.Service.Export.Participants.Common do
     formats = Keyword.get(export_config, :formats, [])
     type in formats
   end
+
+  @default_upload_path "uploads/exports/"
+
+  @spec export_path(String.t()) :: String.t()
+  def export_path(extension) do
+    [:exports, :path]
+    |> Config.get(@default_upload_path)
+    |> Path.join(extension)
+  end
 end
diff --git a/lib/service/export/participants/csv.ex b/lib/service/export/participants/csv.ex
index 62cbdbb3f..b33fbb581 100644
--- a/lib/service/export/participants/csv.ex
+++ b/lib/service/export/participants/csv.ex
@@ -3,17 +3,21 @@ defmodule Mobilizon.Service.Export.Participants.CSV do
   Export a list of participants to CSV
   """
 
-  alias Mobilizon.Events
+  alias Mobilizon.{Events, Export}
   alias Mobilizon.Events.Event
-  alias Mobilizon.Export
   alias Mobilizon.Storage.Repo
   alias Mobilizon.Web.Gettext
   import Mobilizon.Web.Gettext, only: [gettext: 2]
 
   import Mobilizon.Service.Export.Participants.Common,
-    only: [save_upload: 5, columns: 0, to_list: 1, clean_exports: 2, export_enabled?: 1]
-
-  @upload_path "uploads/exports/csv/"
+    only: [
+      save_upload: 5,
+      columns: 0,
+      to_list: 1,
+      clean_exports: 2,
+      export_enabled?: 1,
+      export_path: 1
+    ]
 
   @extension "csv"
 
@@ -26,7 +30,7 @@ defmodule Mobilizon.Service.Export.Participants.CSV do
   def export(%Event{id: event_id} = event, options \\ []) do
     if ready?() do
       filename = "#{ShortUUID.encode!(Ecto.UUID.generate())}.csv"
-      full_path = @upload_path <> filename
+      full_path = Path.join([export_path(@extension), filename])
 
       file = File.open!(full_path, [:write, :utf8])
 
@@ -80,7 +84,7 @@ defmodule Mobilizon.Service.Export.Participants.CSV do
   """
   @spec clean_exports :: :ok
   def clean_exports do
-    clean_exports("csv", @upload_path)
+    clean_exports("csv", export_path(@extension))
   end
 
   @spec dependencies_ok? :: boolean
diff --git a/lib/service/export/participants/ods.ex b/lib/service/export/participants/ods.ex
index e6eb6c4c9..ef73d25fe 100644
--- a/lib/service/export/participants/ods.ex
+++ b/lib/service/export/participants/ods.ex
@@ -10,9 +10,14 @@ defmodule Mobilizon.Service.Export.Participants.ODS do
   import Mobilizon.Web.Gettext, only: [gettext: 2]
 
   import Mobilizon.Service.Export.Participants.Common,
-    only: [save_upload: 5, to_list: 1, clean_exports: 2, columns: 0, export_enabled?: 1]
-
-  @upload_path "uploads/exports/ods/"
+    only: [
+      save_upload: 5,
+      to_list: 1,
+      clean_exports: 2,
+      columns: 0,
+      export_enabled?: 1,
+      export_path: 1
+    ]
 
   @extension "ods"
 
@@ -25,7 +30,7 @@ defmodule Mobilizon.Service.Export.Participants.ODS do
   def export(%Event{id: event_id} = event, options \\ []) do
     if ready?() do
       filename = "#{ShortUUID.encode!(Ecto.UUID.generate())}.ods"
-      full_path = @upload_path <> filename
+      full_path = Path.join([export_path(@extension), filename])
 
       case Repo.transaction(
              fn ->
@@ -84,7 +89,7 @@ defmodule Mobilizon.Service.Export.Participants.ODS do
   """
   @spec clean_exports :: :ok
   def clean_exports do
-    clean_exports("ods", @upload_path)
+    clean_exports(@extension, export_path(@extension))
   end
 
   @spec dependencies_ok? :: boolean
diff --git a/lib/service/export/participants/pdf.ex b/lib/service/export/participants/pdf.ex
index 3d488e6c5..a51e3a08e 100644
--- a/lib/service/export/participants/pdf.ex
+++ b/lib/service/export/participants/pdf.ex
@@ -12,9 +12,14 @@ defmodule Mobilizon.Service.Export.Participants.PDF do
   import Mobilizon.Web.Gettext, only: [gettext: 2]
 
   import Mobilizon.Service.Export.Participants.Common,
-    only: [save_upload: 5, columns: 0, to_list: 1, clean_exports: 2, export_enabled?: 1]
-
-  @upload_path "uploads/exports/pdf/"
+    only: [
+      save_upload: 5,
+      columns: 0,
+      to_list: 1,
+      clean_exports: 2,
+      export_enabled?: 1,
+      export_path: 1
+    ]
 
   @extension "pdf"
 
@@ -27,7 +32,7 @@ defmodule Mobilizon.Service.Export.Participants.PDF do
   def export(%Event{id: event_id} = event, options \\ []) do
     if ready?() do
       filename = "#{ShortUUID.encode!(Ecto.UUID.generate())}.pdf"
-      full_path = @upload_path <> filename
+      full_path = Path.join([export_path(@extension), filename])
 
       case Repo.transaction(
              fn ->
@@ -98,7 +103,7 @@ defmodule Mobilizon.Service.Export.Participants.PDF do
   """
   @spec clean_exports :: :ok
   def clean_exports do
-    clean_exports("pdf", @upload_path)
+    clean_exports(@extension, export_path(@extension))
   end
 
   @spec dependencies_ok? :: boolean
diff --git a/lib/web/controllers/export_controller.ex b/lib/web/controllers/export_controller.ex
index e0d01867a..ce937b68d 100644
--- a/lib/web/controllers/export_controller.ex
+++ b/lib/web/controllers/export_controller.ex
@@ -6,7 +6,7 @@ defmodule Mobilizon.Web.ExportController do
   plug(:put_layout, false)
   action_fallback(Mobilizon.Web.FallbackController)
   alias Mobilizon.Export
-  import Mobilizon.Service.Export.Participants.Common, only: [enabled_formats: 0]
+  import Mobilizon.Service.Export.Participants.Common, only: [enabled_formats: 0, export_path: 1]
   import Mobilizon.Web.Gettext, only: [dgettext: 3]
 
   # sobelow_skip ["Traversal.SendDownload"]
@@ -15,7 +15,7 @@ defmodule Mobilizon.Web.ExportController do
     if format in enabled_formats() do
       case Export.get_export(file, "event_participants", format) do
         %Export{file_name: file_name, file_path: file_path} ->
-          local_path = "uploads/exports/#{format}/#{file_path}"
+          local_path = Path.join(export_path(format), file_path)
           # We're using encode: false to disable escaping the filename with URI.encode_www_form/1
           # but it may introduce an security issue if the event title wasn't properly sanitized
           # https://github.com/phoenixframework/phoenix/pull/3344

From 233cf1026ab57ff952359061916af994e2be9e5c Mon Sep 17 00:00:00 2001
From: Thomas Citharel <tcit@tcit.fr>
Date: Mon, 22 Nov 2021 19:38:36 +0100
Subject: [PATCH 3/7] Improve the UPGRADE.md file

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
---
 UPGRADE.md | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/UPGRADE.md b/UPGRADE.md
index 566f70c63..9e243afbd 100644
--- a/UPGRADE.md
+++ b/UPGRADE.md
@@ -8,7 +8,7 @@ You are already using latest Elixir version in the release tarball and Docker im
 
 ### Source install
 
-**Elixir 1.12 and Erlang OTP 22 are now required**. If your distribution doesn't provide these versions (which is likely), you must uninstall them and install [Elixir](https://github.com/asdf-vm/asdf-elixir) through the [ASDF tool](https://asdf-vm.com/).
+**Elixir 1.12 and Erlang OTP 22 are now required**. If your distribution or the repositories from Erlang Solutions don't provide these versions, you need to uninstall the current versions and install [Elixir](https://github.com/asdf-vm/asdf-elixir) through the [ASDF tool](https://asdf-vm.com/).
 
 ## Geographic timezone data
 
@@ -61,6 +61,17 @@ In both cases, ~700Mio of disk will be used. You may use the following configura
 config :tz_world, data_dir: "/some/place"
 ```
 
+## Exports folder
+
+Create the folder for default CSV export:
+
+```sh
+sudo -u mobilizon mkdir -p /var/lib/mobilizon/uploads/exports/csv
+```
+
+This path can be configured, see [the dedicated docs page about this](https://docs.joinmobilizon.org/administration/configure/exports/).
+Files in this folder are temporary and are cleaned once an hour.
+
 ## New optional dependencies
 
 These are optional, installing them will allow Mobilizon to export to PDF and ODS as well. Mobilizon 2.0 allows to export the participant list, but more is planned.
@@ -73,7 +84,7 @@ New optional Python dependencies:
 * `weasyprint` for PDF export (with [a few extra dependencies](https://doc.courtbouillon.org/weasyprint/stable/first_steps.html))
 * `pyexcel-ods3` for ODS export (no extra dependencies)
 
-Both can be installed through pip. You need to enable exports for PDF and ODS in the configuration afterwards. Read [the dedicated docs page about this]() (*upcoming*).
+Both can be installed through pip. You need to enable and configure exports for PDF and ODS in the configuration afterwards. Read [the dedicated docs page about this](https://docs.joinmobilizon.org/administration/configure/exports/).
 
 # Upgrading from 1.0 to 1.1
 

From a54b879c2d53e9fea4dfedd658ee15702abb494a Mon Sep 17 00:00:00 2001
From: Thomas Citharel <tcit@tcit.fr>
Date: Mon, 22 Nov 2021 19:38:53 +0100
Subject: [PATCH 4/7] Enable exports on Docker

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
---
 config/docker.exs | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/config/docker.exs b/config/docker.exs
index e370644e8..084f96c70 100644
--- a/config/docker.exs
+++ b/config/docker.exs
@@ -68,5 +68,13 @@ config :geolix,
 config :mobilizon, Mobilizon.Web.Upload.Uploader.Local,
   uploads: System.get_env("MOBILIZON_UPLOADS", "/var/lib/mobilizon/uploads")
 
+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
+  ]
+
 config :tz_world,
   data_dir: System.get_env("MOBILIZON_TIMEZONES_DIR", "/var/lib/mobilizon/timezones")

From d4dfba48d8f633a57d77573da5f36e47fbf51a5e Mon Sep 17 00:00:00 2001
From: Thomas Citharel <tcit@tcit.fr>
Date: Mon, 22 Nov 2021 20:00:01 +0100
Subject: [PATCH 5/7] Fix error page when ends_on date is null

Closes #936

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
---
 js/src/filters/datetime.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/js/src/filters/datetime.ts b/js/src/filters/datetime.ts
index e5fdb2725..bdc14e7d3 100644
--- a/js/src/filters/datetime.ts
+++ b/js/src/filters/datetime.ts
@@ -56,7 +56,7 @@ const SHORT_TIME_FORMAT_OPTIONS: DateTimeFormatOptions = {
 
 function formatDateTimeString(
   value: string,
-  timeZone: string | undefined = undefined,
+  timeZone: string | null | undefined = undefined,
   showTime = true,
   dateFormat = "long"
 ): string {
@@ -68,7 +68,7 @@ function formatDateTimeString(
     options = {
       ...options,
       ...(isLongFormat ? LONG_TIME_FORMAT_OPTIONS : SHORT_TIME_FORMAT_OPTIONS),
-      timeZone,
+      timeZone: timeZone || undefined,
     };
   }
   const format = new Intl.DateTimeFormat(locale(), options);

From 0ec42186367b59be92cf72e9bec31131cd1ebb1a Mon Sep 17 00:00:00 2001
From: Thomas Citharel <tcit@tcit.fr>
Date: Mon, 22 Nov 2021 19:41:07 +0100
Subject: [PATCH 6/7] Update CHANGELOG.md for 2.0.0-rc.3

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
---
 CHANGELOG.md | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e2fd22493..eb92f3a69 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## 2.0.0-rc.3 - 2021-11-22
+
+This lists changes since 2.0.0-rc.3. Please read the [UPGRADE.md](https://framagit.org/framasoft/mobilizon/-/blob/main/UPGRADE.md#upgrading-from-13-to-20) file as well.
+
+### Fixed
+
+- Fixed path to exports in production
+- Fixed padding below truncated title of event cards
+- Fixed exports that weren't enabled in Docker
+- Fixed error page when event end date is null
+
 ## 2.0.0-rc.2 - 2021-11-22
 
 This lists changes since 2.0.0-rc.1. Please read the [UPGRADE.md](https://framagit.org/framasoft/mobilizon/-/blob/main/UPGRADE.md#upgrading-from-13-to-20) file as well.

From 20eea58ac96dd174fc7829de9a5bb33bdeea64e1 Mon Sep 17 00:00:00 2001
From: Thomas Citharel <tcit@tcit.fr>
Date: Mon, 22 Nov 2021 19:41:34 +0100
Subject: [PATCH 7/7] Bump version to 2.0.0-rc.3

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
---
 js/package.json | 2 +-
 mix.exs         | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/js/package.json b/js/package.json
index 8410577b2..7bf3d01f1 100644
--- a/js/package.json
+++ b/js/package.json
@@ -1,6 +1,6 @@
 {
   "name": "mobilizon",
-  "version": "2.0.0-rc.2",
+  "version": "2.0.0-rc.3",
   "private": true,
   "scripts": {
     "serve": "vue-cli-service serve",
diff --git a/mix.exs b/mix.exs
index 498815306..0198d7ee8 100644
--- a/mix.exs
+++ b/mix.exs
@@ -1,7 +1,7 @@
 defmodule Mobilizon.Mixfile do
   use Mix.Project
 
-  @version "2.0.0-rc.2"
+  @version "2.0.0-rc.3"
 
   def project do
     [