diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1883f8ef0..797504dec 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -4,7 +4,6 @@ stages:
- install
- check
- build-js
- - sentry
- test
- build
- upload
@@ -93,21 +92,6 @@ build-frontend:
needs:
- lint-front
-sentry-commit:
- stage: sentry
- image: getsentry/sentry-cli
- script:
- - echo "Create a new release $CI_COMMIT_TAG"
- - sentry-cli releases new $CI_COMMIT_TAG
- - sentry-cli releases set-commits $CI_COMMIT_TAG --auto
- - sentry-cli releases files $CI_COMMIT_TAG upload-sourcemaps priv/static/assets/
- - sentry-cli releases finalize $CI_COMMIT_TAG
- - echo "Finalized release for $CI_COMMIT_TAG"
- needs:
- - build-frontend
- only:
- - tags@framasoft/mobilizon
-
deps:
stage: check
before_script:
@@ -162,6 +146,8 @@ vitest:
e2e:
stage: test
+ except:
+ - tags@framasoft/mobilizon
services:
- name: postgis/postgis:16-3.4
alias: postgres
diff --git a/default.nix b/default.nix
index 3f83816f3..dcfe2ec1d 100644
--- a/default.nix
+++ b/default.nix
@@ -17,7 +17,7 @@ mixRelease rec {
# This has to be kept in sync with the version in mix.exs and package.json!
# Otherwise the nginx routing isn't going to work properly.
- version = "5.0.0-beta.1";
+ version = "5.1.0";
inherit src;
diff --git a/integration-test.nix b/integration-test.nix
index 57794041f..d98f8dda5 100644
--- a/integration-test.nix
+++ b/integration-test.nix
@@ -28,6 +28,8 @@ in
};
};
+ systemd.services.mobilizon-postgresql.serviceConfig.Restart = "on-failure";
+
services.postgresql.package = pkgs.postgresql_14;
security.pki.certificateFiles = [ certs.ca.cert ];
diff --git a/lib/graphql/api/search.ex b/lib/graphql/api/search.ex
index eba18c20f..d7ef8da0b 100644
--- a/lib/graphql/api/search.ex
+++ b/lib/graphql/api/search.ex
@@ -57,7 +57,8 @@ defmodule Mobilizon.GraphQL.API.Search do
current_actor_id: Map.get(args, :current_actor_id),
exclude_my_groups: Map.get(args, :exclude_my_groups, false),
exclude_stale_actors: true,
- local_only: Map.get(args, :search_target, :internal) == :self
+ local_only: Map.get(args, :search_target, :internal) == :self,
+ sort_by: Map.get(args, :sort_by)
],
page,
limit
diff --git a/lib/graphql/resolvers/event.ex b/lib/graphql/resolvers/event.ex
index fe7aaec69..04ab9b8c5 100644
--- a/lib/graphql/resolvers/event.ex
+++ b/lib/graphql/resolvers/event.ex
@@ -76,7 +76,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
limit: limit,
order_by: order_by,
direction: direction,
- longevents: longevents,
+ long_events: long_events,
location: location,
radius: radius
},
@@ -84,7 +84,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
)
when limit < @event_max_limit do
{:ok,
- Events.list_events(page, limit, order_by, direction, true, longevents, location, radius)}
+ Events.list_events(page, limit, order_by, direction, true, long_events, location, radius)}
end
def list_events(
diff --git a/lib/graphql/schema/event.ex b/lib/graphql/schema/event.ex
index 4ecd682fe..253756319 100644
--- a/lib/graphql/schema/event.ex
+++ b/lib/graphql/schema/event.ex
@@ -32,6 +32,11 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
field(:description, :string, description: "The event's description")
field(:begins_on, :datetime, description: "Datetime for when the event begins")
field(:ends_on, :datetime, description: "Datetime for when the event ends")
+
+ field(:long_event, :boolean,
+ description: "Whether the event is a long event (activity) or not"
+ )
+
field(:status, :event_status, description: "Status of the event")
field(:visibility, :event_visibility, description: "The event's visibility")
field(:join_options, :event_join_options, description: "The event's visibility")
@@ -395,7 +400,7 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
description: "Direction for the sort"
)
- arg(:longevents, :boolean,
+ arg(:long_events, :boolean,
default_value: nil,
description: "if mention filter in or out long events"
)
diff --git a/lib/graphql/schema/search.ex b/lib/graphql/schema/search.ex
index f518c13dc..7d8448102 100644
--- a/lib/graphql/schema/search.ex
+++ b/lib/graphql/schema/search.ex
@@ -17,6 +17,11 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do
field(:title, :string, description: "The event's title")
field(:begins_on, :datetime, description: "Datetime for when the event begins")
field(:ends_on, :datetime, description: "Datetime for when the event ends")
+
+ field(:long_event, :boolean,
+ description: "Whether the event is a long event (activity) or not"
+ )
+
field(:status, :event_status, description: "Status of the event")
field(:picture, :media, description: "The event's picture")
field(:physical_address, :address, description: "The event's physical address")
@@ -52,6 +57,11 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do
field(:title, :string, description: "The event's title")
field(:begins_on, :datetime, description: "Datetime for when the event begins")
field(:ends_on, :datetime, description: "Datetime for when the event ends")
+
+ field(:long_event, :boolean,
+ description: "Whether the event is a long event (activity) or not"
+ )
+
field(:status, :event_status, description: "Status of the event")
field(:picture, :media, description: "The event's picture")
field(:physical_address, :address, description: "The event's physical address")
@@ -171,7 +181,11 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do
enum :search_group_sort_options do
value(:match_desc, description: "The pertinence of the result")
- value(:member_count_desc, description: "The members count of the group")
+ value(:member_count_asc, description: "The members count of the group ascendant order")
+ value(:member_count_desc, description: "The members count of the group descendent order")
+ value(:created_at_asc, description: "When the group was created ascendant order")
+ value(:created_at_desc, description: "When the group was created descendent order")
+ value(:last_event_activity, description: "Last event activity of the group")
end
enum :search_event_sort_options do
@@ -273,7 +287,7 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do
description: "Radius around the location to search in"
)
- arg(:longevents, :boolean, description: "if mention filter in or out long events")
+ arg(:long_events, :boolean, description: "if mention filter in or out long events")
arg(:bbox, :string, description: "The bbox to search events into")
arg(:zoom, :integer, description: "The zoom level for searching events")
diff --git a/lib/mobilizon/actors/actors.ex b/lib/mobilizon/actors/actors.ex
index cc78c0807..1349b32f7 100644
--- a/lib/mobilizon/actors/actors.ex
+++ b/lib/mobilizon/actors/actors.ex
@@ -13,6 +13,7 @@ defmodule Mobilizon.Actors do
alias Mobilizon.Actors.{Actor, Bot, Follower, Member}
alias Mobilizon.Addresses.Address
alias Mobilizon.Crypto
+ alias Mobilizon.Events.Event
alias Mobilizon.Events.FeedToken
alias Mobilizon.Medias
alias Mobilizon.Service.Workers
@@ -518,7 +519,6 @@ defmodule Mobilizon.Actors do
query = from(a in Actor)
query
- |> distinct([q], q.id)
|> actor_by_username_or_name_query(term)
|> maybe_join_address(
Keyword.get(options, :location),
@@ -532,8 +532,56 @@ defmodule Mobilizon.Actors do
|> filter_by_minimum_visibility(Keyword.get(options, :minimum_visibility, :public))
|> filter_suspended(false)
|> filter_out_anonymous_actor_id(anonymous_actor_id)
+ # order_by
+ |> actor_order(Keyword.get(options, :sort_by, :match_desc))
end
+ # sort by most recent id if "best match"
+ defp actor_order(query, :match_desc) do
+ query
+ |> order_by([q], desc: q.id)
+ end
+
+ defp actor_order(query, :last_event_activity) do
+ query
+ |> join(:left, [q], e in Event, on: e.attributed_to_id == q.id)
+ |> group_by([q, e], q.id)
+ |> order_by([q, e], [
+ # put groups with no events at the end of the list
+ fragment("MAX(?) IS NULL", e.updated_at),
+ # last edited event of the group
+ desc: max(e.updated_at),
+ # sort group with no event by id
+ desc: q.id
+ ])
+ end
+
+ defp actor_order(query, :member_count_asc) do
+ query
+ |> join(:left, [q], m in Member, on: m.parent_id == q.id)
+ |> group_by([q, m], q.id)
+ |> order_by([q, m], asc: count(m.id), asc: q.id)
+ end
+
+ defp actor_order(query, :member_count_desc) do
+ query
+ |> join(:left, [q], m in Member, on: m.parent_id == q.id)
+ |> group_by([q, m], q.id)
+ |> order_by([q, m], desc: count(m.id), desc: q.id)
+ end
+
+ defp actor_order(query, :created_at_asc) do
+ query
+ |> order_by([q], asc: q.inserted_at)
+ end
+
+ defp actor_order(query, :created_at_desc) do
+ query
+ |> order_by([q], desc: q.inserted_at)
+ end
+
+ defp actor_order(query, _), do: query
+
@doc """
Gets a group by its title.
"""
@@ -1394,16 +1442,6 @@ defmodule Mobilizon.Actors do
^username
)
)
- |> order_by(
- [a],
- fragment(
- "word_similarity(?, ?) + word_similarity(coalesce(?, ''), ?) desc",
- a.preferred_username,
- ^username,
- a.name,
- ^username
- )
- )
end
@spec maybe_join_address(
diff --git a/lib/mobilizon/events/event.ex b/lib/mobilizon/events/event.ex
index ff76568ae..8e39f5e70 100644
--- a/lib/mobilizon/events/event.ex
+++ b/lib/mobilizon/events/event.ex
@@ -66,6 +66,7 @@ defmodule Mobilizon.Events.Event do
participants: [Actor.t()],
contacts: [Actor.t()],
language: String.t(),
+ long_event: boolean,
metadata: [EventMetadata.t()]
}
@@ -89,7 +90,8 @@ defmodule Mobilizon.Events.Event do
:picture_id,
:physical_address_id,
:attributed_to_id,
- :language
+ :language,
+ :long_event
]
@attrs @required_attrs ++ @optional_attrs
@@ -102,6 +104,7 @@ defmodule Mobilizon.Events.Event do
field(:slug, :string)
field(:description, :string)
field(:ends_on, :utc_datetime)
+ field(:long_event, :boolean, virtual: true, default: nil)
field(:title, :string)
field(:status, EventStatus, default: :confirmed)
field(:draft, :boolean, default: false)
diff --git a/lib/mobilizon/events/events.ex b/lib/mobilizon/events/events.ex
index 4d68b9d41..f741354c3 100644
--- a/lib/mobilizon/events/events.ex
+++ b/lib/mobilizon/events/events.ex
@@ -12,6 +12,8 @@ defmodule Mobilizon.Events do
import Mobilizon.Storage.Ecto
import Mobilizon.Events.Utils, only: [calculate_notification_time: 1]
+ require Logger
+
alias Ecto.{Changeset, Multi}
alias Mobilizon.Actors.{Actor, Follower}
@@ -141,6 +143,7 @@ defmodule Mobilizon.Events do
url
|> event_by_url_query()
|> Repo.one()
+ |> with_virtual_fields()
end
@doc """
@@ -153,6 +156,7 @@ defmodule Mobilizon.Events do
|> event_by_url_query()
|> preload_for_event()
|> Repo.one!()
+ |> with_virtual_fields()
end
@doc """
@@ -167,6 +171,7 @@ defmodule Mobilizon.Events do
|> filter_draft()
|> preload_for_event()
|> Repo.one!()
+ |> with_virtual_fields()
end
@doc """
@@ -180,6 +185,7 @@ defmodule Mobilizon.Events do
|> filter_draft()
|> preload_for_event()
|> Repo.one()
+ |> with_virtual_fields()
end
@spec check_if_event_has_instance_follow(String.t(), integer()) :: boolean()
@@ -199,6 +205,7 @@ defmodule Mobilizon.Events do
|> event_by_uuid_query()
|> preload_for_event()
|> Repo.one()
+ |> with_virtual_fields()
end
@doc """
@@ -212,6 +219,7 @@ defmodule Mobilizon.Events do
|> filter_not_event_uuid(not_event_uuid)
|> filter_draft()
|> Repo.one()
+ |> with_virtual_fields()
end
@doc """
@@ -366,7 +374,7 @@ defmodule Mobilizon.Events do
atom,
boolean,
boolean | nil,
- string | nil,
+ String.t() | nil,
float | nil
) :: Page.t(Event.t())
def list_events(
@@ -375,7 +383,7 @@ defmodule Mobilizon.Events do
sort \\ :begins_on,
direction \\ :asc,
is_future \\ true,
- longevents \\ nil,
+ long_events \\ nil,
location \\ nil,
radius \\ nil
) do
@@ -386,12 +394,13 @@ defmodule Mobilizon.Events do
|> maybe_join_address(%{location: location, radius: radius})
|> events_for_location(%{location: location, radius: radius})
|> filter_future_events(is_future)
- |> events_for_longevents(longevents)
+ |> events_for_long_events(long_events)
|> filter_public_visibility()
|> filter_draft()
|> filter_cancelled_events()
|> filter_local_or_from_followed_instances_events()
|> Page.build_page(page, limit)
+ |> with_virtual_fields()
end
@spec stream_events_for_sitemap :: Enum.t()
@@ -413,6 +422,7 @@ defmodule Mobilizon.Events do
|> preload_for_event()
|> event_order_by(sort, direction)
|> Page.build_page(page, limit)
+ |> with_virtual_fields()
end
@doc """
@@ -425,6 +435,7 @@ defmodule Mobilizon.Events do
|> events_by_tags_query(limit)
|> filter_draft()
|> Repo.all()
+ |> with_virtual_fields()
end
@doc """
@@ -440,6 +451,7 @@ defmodule Mobilizon.Events do
actor_id
|> do_list_public_events_for_actor()
|> Page.build_page(page, limit)
+ |> with_virtual_fields()
end
@doc """
@@ -467,6 +479,7 @@ defmodule Mobilizon.Events do
|> do_list_public_events_for_actor()
|> event_filter_begins_on(DateTime.utc_now(), nil)
|> Page.build_page(page, limit)
+ |> with_virtual_fields()
end
@spec do_list_public_events_for_actor(integer()) :: Ecto.Query.t()
@@ -485,6 +498,7 @@ defmodule Mobilizon.Events do
|> event_for_actor_query(desc: :begins_on)
|> preload_for_event()
|> Page.build_page(page, limit)
+ |> with_virtual_fields()
end
@spec list_simple_organized_events_for_group(Actor.t(), integer | nil, integer | nil) ::
@@ -516,10 +530,13 @@ defmodule Mobilizon.Events do
group_id
|> event_for_group_query()
|> event_filter_visibility(visibility)
- |> event_filter_begins_on(after_datetime, before_datetime)
+ # We want future and ongoing events, so we use ends_on
+ # See issue #1567
+ |> event_filter_ends_on(after_datetime, before_datetime)
|> event_order_by(order_by, order_direction)
|> preload_for_event()
|> Page.build_page(page, limit)
+ |> with_virtual_fields()
end
@spec list_drafts_for_user(integer, integer | nil, integer | nil) :: Page.t(Event.t())
@@ -529,6 +546,7 @@ defmodule Mobilizon.Events do
|> filter_draft(true)
|> order_by(desc: :updated_at)
|> Page.build_page(page, limit)
+ |> with_virtual_fields()
end
@spec user_moderator_for_event?(integer | String.t(), integer | String.t()) :: boolean
@@ -552,6 +570,7 @@ defmodule Mobilizon.Events do
|> close_events_query(radius)
|> filter_draft()
|> Repo.all()
+ |> with_virtual_fields()
end
@doc """
@@ -587,7 +606,7 @@ defmodule Mobilizon.Events do
|> events_for_search_query()
|> events_for_begins_on(Map.get(args, :begins_on, DateTime.utc_now()))
|> events_for_ends_on(Map.get(args, :ends_on))
- |> events_for_longevents(Map.get(args, :longevents))
+ |> events_for_long_events(Map.get(args, :long_events))
|> events_for_category(args)
|> events_for_categories(args)
|> events_for_languages(args)
@@ -602,7 +621,8 @@ defmodule Mobilizon.Events do
|> filter_local_or_from_followed_instances_events()
|> filter_public_visibility()
|> event_order(Map.get(args, :sort_by, :match_desc), search_string)
- |> Page.build_page(page, limit, :begins_on)
+ |> Page.build_page(page, limit)
+ |> with_virtual_fields()
end
@doc """
@@ -978,6 +998,7 @@ defmodule Mobilizon.Events do
actor_id
|> event_participations_for_actor_query()
|> Page.build_page(page, limit)
+ |> with_virtual_fields()
end
@doc """
@@ -993,6 +1014,7 @@ defmodule Mobilizon.Events do
actor_id
|> event_participations_for_actor_query(DateTime.utc_now())
|> Page.build_page(page, limit)
+ |> with_virtual_fields()
end
@doc """
@@ -1394,14 +1416,14 @@ defmodule Mobilizon.Events do
end
end
- @spec events_for_longevents(Ecto.Queryable.t(), Boolean.t() | nil) :: Ecto.Query.t()
- defp events_for_longevents(query, longevents) do
+ @spec events_for_long_events(Ecto.Queryable.t(), Boolean.t() | nil) :: Ecto.Query.t()
+ defp events_for_long_events(query, long_events) do
duration = Config.get([:instance, :duration_of_long_event], 0)
if duration <= 0 do
query
else
- case longevents do
+ case long_events do
nil ->
query
@@ -1871,6 +1893,7 @@ defmodule Mobilizon.Events do
)
)
|> Repo.all()
+ |> with_virtual_fields()
end
@spec list_participations_for_user_query(integer()) :: Ecto.Query.t()
@@ -2003,6 +2026,35 @@ defmodule Mobilizon.Events do
|> where([e], e.begins_on > ^after_datetime)
end
+ defp event_filter_ends_on(query, nil, nil), do: query
+
+ defp event_filter_ends_on(query, %DateTime{} = after_datetime, nil) do
+ where(
+ query,
+ [e],
+ (is_nil(e.ends_on) and e.begins_on >= ^after_datetime) or
+ e.ends_on >= ^after_datetime
+ )
+ end
+
+ defp event_filter_ends_on(query, nil, %DateTime{} = before_datetime) do
+ where(
+ query,
+ [e],
+ (is_nil(e.ends_on) and e.begins_on <= ^before_datetime) or e.ends_on <= ^before_datetime
+ )
+ end
+
+ defp event_filter_ends_on(
+ query,
+ %DateTime{} = after_datetime,
+ %DateTime{} = before_datetime
+ ) do
+ query
+ |> event_filter_ends_on(after_datetime, nil)
+ |> event_filter_ends_on(nil, before_datetime)
+ end
+
defp event_order_by(query, order_by, direction)
when order_by in [:begins_on, :inserted_at, :updated_at] and direction in [:asc, :desc] do
order_by_instruction = Keyword.new([{direction, order_by}])
@@ -2098,4 +2150,44 @@ defmodule Mobilizon.Events do
|> preload_for_event()
|> Page.chunk(chunk_size)
end
+
+ # Handling the case where Repo.XXXX() return nil
+ def with_virtual_fields(nil), do: nil
+
+ # if envent has no end date, it can not be a long events
+ def with_virtual_fields(%Event{} = event) when is_nil(event.ends_on),
+ do: %{event | long_event: false}
+
+ # Handling the case where there is an event
+ # Using Repo.one(), for example
+ def with_virtual_fields(%Event{} = event) do
+ duration = Config.get([:instance, :duration_of_long_event], 0)
+
+ event_duration = DateTime.diff(event.ends_on, event.begins_on, :day)
+
+ # duration need to be > 0 for long event to be activated
+ long_event = duration > 0 && event_duration > duration
+
+ %{event | long_event: long_event}
+ end
+
+ # Handling the case where there is a list of events
+ # Using Repo.all(), for example
+ def with_virtual_fields(events) when is_list(events) do
+ Enum.map(events, &with_virtual_fields/1)
+ end
+
+ # Handling the case of a paginated list of events
+ def with_virtual_fields(%Page{total: _total, elements: elements} = page) do
+ elements_with_virtual_fields = Enum.map(elements, &with_virtual_fields/1)
+ %{page | elements: elements_with_virtual_fields}
+ end
+
+ # In case the function is called on an element without virtual_fields
+ def with_virtual_fields(invalid) do
+ Logger.warning("with_virtual_fields called on invalid element : #{inspect(invalid)}")
+
+ # Return the element without modification
+ invalid
+ end
end
diff --git a/lib/mobilizon/instances/instances.ex b/lib/mobilizon/instances/instances.ex
index db0dafd29..8d6557877 100644
--- a/lib/mobilizon/instances/instances.ex
+++ b/lib/mobilizon/instances/instances.ex
@@ -73,7 +73,7 @@ defmodule Mobilizon.Instances do
query
end
- %Page{elements: elements} = paged_instances = Page.build_page(query, page, limit, :domain)
+ %Page{elements: elements} = paged_instances = Page.build_page(query, page, limit)
%Page{
paged_instances
diff --git a/lib/mobilizon/storage/page.ex b/lib/mobilizon/storage/page.ex
index 6bdf90dc6..cc1ff6de6 100644
--- a/lib/mobilizon/storage/page.ex
+++ b/lib/mobilizon/storage/page.ex
@@ -19,15 +19,23 @@ defmodule Mobilizon.Storage.Page do
@doc """
Returns a Page struct for a query.
-
- `field` is used to define the field that will be used for the count aggregate, which should be the same as the field used for order_by
- See https://stackoverflow.com/q/12693089/10204399
"""
- @spec build_page(Ecto.Queryable.t(), integer | nil, integer | nil, atom()) :: t(any)
- def build_page(query, page, limit, field \\ :id) do
+ @spec build_page(Ecto.Queryable.t(), integer | nil, integer) :: t(any)
+ def build_page(query, page, limit) do
+ count_query =
+ query
+ # Exclude select because we add a new one below
+ |> exclude(:select)
+ # Exclude order_by for perf
+ |> exclude(:order_by)
+ # Exclude preloads to avoid error "cannot preload associations in subquery"
+ |> exclude(:preload)
+ |> subquery()
+ |> select([r], count(fragment("*")))
+
[total, elements] =
[
- fn -> Repo.aggregate(query, :count, field) end,
+ fn -> Repo.one(count_query) end,
fn -> Repo.all(paginate(query, page, limit)) end
]
|> Enum.map(&Task.async/1)
diff --git a/mix.exs b/mix.exs
index d5901e806..e8d2bdd86 100644
--- a/mix.exs
+++ b/mix.exs
@@ -1,7 +1,7 @@
defmodule Mobilizon.Mixfile do
use Mix.Project
- @version "5.0.0-beta.1"
+ @version "5.1.0"
def project do
[
diff --git a/package-lock.json b/package-lock.json
index bdf530331..9c25baef7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,13 @@
{
"name": "mobilizon",
- "version": "5.0.0-beta.1",
+ "version": "5.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mobilizon",
- "version": "5.0.0-beta.1",
+ "version": "5.1.0",
+ "hasInstallScript": true,
"dependencies": {
"@apollo/client": "^3.9.5",
"@framasoft/socket": "^1.0.0",
diff --git a/package.json b/package.json
index 64c143ba1..ebee164cb 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "mobilizon",
- "version": "5.0.0-beta.1",
+ "version": "5.1.0",
"private": true,
"scripts": {
"dev": "vite",
diff --git a/priv/repo/migrations/20240725130410_add_event_physical_address_index.exs b/priv/repo/migrations/20240725130410_add_event_physical_address_index.exs
new file mode 100644
index 000000000..b9201c901
--- /dev/null
+++ b/priv/repo/migrations/20240725130410_add_event_physical_address_index.exs
@@ -0,0 +1,11 @@
+defmodule Mobilizon.Storage.Repo.Migrations.AddEventPhysicalAddressIndex do
+ use Ecto.Migration
+
+ def up do
+ create(index("events", [:physical_address_id], name: :events_phys_addr_id))
+ end
+
+ def down do
+ drop(index("events", [:physical_address_id], name: :events_phys_addr_id))
+ end
+end
diff --git a/schema.graphql b/schema.graphql
index 372868580..1e5d1e707 100644
--- a/schema.graphql
+++ b/schema.graphql
@@ -2268,7 +2268,7 @@ type RootQueryType {
endsOn: DateTime
"Filter for long events in function of configuration parameter 'duration_of_long_event'"
- longevents: Boolean
+ longEvents: Boolean
): Events
"Interact with an URI"
diff --git a/src/assets/oruga-tailwindcss.css b/src/assets/oruga-tailwindcss.css
index 8f33ffe8b..0d5941ebe 100644
--- a/src/assets/oruga-tailwindcss.css
+++ b/src/assets/oruga-tailwindcss.css
@@ -210,7 +210,7 @@ body {
}
.checkbox-check {
- @apply appearance-none bg-primary border-primary;
+ @apply appearance-none border-primary;
}
.checkbox-checked {
@@ -250,7 +250,7 @@ body {
@apply mr-2;
}
.form-radio {
- @apply bg-none text-primary accent-primary;
+ @apply bg-none text-primary border-primary accent-primary;
}
.radio-label {
@apply pl-2;
diff --git a/src/components/Event/EventActionSection.vue b/src/components/Event/EventActionSection.vue
index eb8e3d41b..a7b855ff4 100644
--- a/src/components/Event/EventActionSection.vue
+++ b/src/components/Event/EventActionSection.vue
@@ -110,67 +110,66 @@
{{ t("Actions") }}
-
-
- {{
- t("On {date} from {startTime} to {endTime}", {
- date: formatDate(beginsOn),
- startTime: formatTime(beginsOn, timezoneToShow),
- endTime: formatTime(endsOn, timezoneToShow),
- })
- }}
-
-
- {{ - t("On {date} starting at {startTime}", { - date: formatDate(beginsOn), - startTime: formatTime(beginsOn, timezoneToShow), - }) - }} -
-- {{ t("On {date}", { date: formatDate(beginsOn) }) }} -
-
+
+
+
+ {{
+ t("On {date} from {startTime} to {endTime}", {
+ date: formatDate(beginsOn),
+ startTime: formatTime(beginsOn),
+ endTime: formatTime(endsOn),
+ })
+ }}
+
+ {{
+ t("On {date} starting at {startTime}", {
+ date: formatDate(beginsOn),
+ startTime: formatTime(beginsOn),
+ })
+ }}
+
+ {{
+ t("On {date} ending at {endTime}", {
+ date: formatDate(beginsOn),
+ endTime: formatTime(endsOn),
+ })
+ }}
+
+ {{ t("On {date}", { date: formatDate(beginsOn) }) }}
+
{{
t("From the {startDate} at {startTime} to the {endDate} at {endTime}", {
startDate: formatDate(beginsOn),
- startTime: formatTime(beginsOn, timezoneToShow),
+ startTime: formatTime(beginsOn),
endDate: formatDate(endsOn),
- endTime: formatTime(endsOn, timezoneToShow),
+ endTime: formatTime(endsOn),
})
}}
-
-
+
{{
t("From the {startDate} at {startTime} to the {endDate}", {
startDate: formatDate(beginsOn),
- startTime: formatTime(beginsOn, timezoneToShow),
+ startTime: formatTime(beginsOn),
endDate: formatDate(endsOn),
})
}}
-
-
+
+ + {{ + t("From the {startDate} to the {endDate} at {endTime}", { + startDate: formatDate(beginsOn), + endDate: formatDate(endsOn), + endTime: formatTime(endsOn), + }) + }} + +
+{{ t("From the {startDate} to the {endDate}", { startDate: formatDate(beginsOn), @@ -87,6 +78,13 @@ }) }}
+{{ $t("Add a contact") }}