diff --git a/js/src/graphql/event.ts b/js/src/graphql/event.ts index c0e1e904..87e54ecb 100644 --- a/js/src/graphql/event.ts +++ b/js/src/graphql/event.ts @@ -295,7 +295,7 @@ export const JOIN_EVENT = gql` $email: String $message: String $locale: String - $timezone: String + $timezone: Timezone ) { joinEvent( eventId: $eventId diff --git a/js/src/graphql/user.ts b/js/src/graphql/user.ts index e902488f..33ef1bff 100644 --- a/js/src/graphql/user.ts +++ b/js/src/graphql/user.ts @@ -151,7 +151,7 @@ export const LOGGED_USER_TIMEZONE = gql` export const SET_USER_SETTINGS = gql` mutation SetUserSettings( - $timezone: String + $timezone: Timezone $notificationOnDay: Boolean $notificationEachWeek: Boolean $notificationBeforeEvent: Boolean diff --git a/lib/graphql/schema.ex b/lib/graphql/schema.ex index b74385db..b635bc72 100644 --- a/lib/graphql/schema.ex +++ b/lib/graphql/schema.ex @@ -31,6 +31,7 @@ defmodule Mobilizon.GraphQL.Schema do import_types(Absinthe.Plug.Types) import_types(Custom.UUID) import_types(Custom.Point) + import_types(Custom.Timezone) import_types(Schema.ActivityType) import_types(Schema.UserType) diff --git a/lib/graphql/schema/address.ex b/lib/graphql/schema/address.ex index 0ca407f1..f1ec42a9 100644 --- a/lib/graphql/schema/address.ex +++ b/lib/graphql/schema/address.ex @@ -22,7 +22,7 @@ defmodule Mobilizon.GraphQL.Schema.AddressType do field(:url, :string, description: "The address's URL") field(:id, :id, description: "The address's ID") field(:origin_id, :string, description: "The address's original ID from the provider") - field(:timezone, :string, description: "The (estimated) timezone of the location") + field(:timezone, :timezone, description: "The (estimated) timezone of the location") field(:picture_info, :picture_info, description: "A picture associated with the address") end @@ -75,7 +75,7 @@ defmodule Mobilizon.GraphQL.Schema.AddressType do field(:url, :string, description: "The address's URL") field(:id, :id, description: "The address's ID") field(:origin_id, :string, description: "The address's original ID from the provider") - field(:timezone, :string, description: "The (estimated) timezone of the location") + field(:timezone, :timezone, description: "The (estimated) timezone of the location") end @desc """ diff --git a/lib/graphql/schema/config.ex b/lib/graphql/schema/config.ex index 19c2fbec..cc42f1b1 100644 --- a/lib/graphql/schema/config.ex +++ b/lib/graphql/schema/config.ex @@ -43,7 +43,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do field(:upload_limits, :upload_limits, description: "The configuration for upload limits") - field(:timezones, list_of(:string), description: "The instance's available timezones") + field(:timezones, list_of(:timezone), description: "The instance's available timezones") field(:features, :features, description: "The instance's features") field(:restrictions, :restrictions, description: "The instance's restrictions") field(:version, :string, description: "The instance's version") diff --git a/lib/graphql/schema/custom/timezone.ex b/lib/graphql/schema/custom/timezone.ex new file mode 100644 index 00000000..cd20efc0 --- /dev/null +++ b/lib/graphql/schema/custom/timezone.ex @@ -0,0 +1,35 @@ +defmodule Mobilizon.GraphQL.Schema.Custom.Timezone do + @moduledoc """ + The timezone scalar type allows timezone ID strings to be passed in and out. + """ + use Absinthe.Schema.Notation + import Mobilizon.Web.Gettext, only: [dgettext: 3] + + scalar :timezone, name: "Timezone" do + description(""" + The `Timezone` scalar type represents a timezone identifier, + as registered in the IANA Time Zone Database. + """) + + serialize(&encode/1) + parse(&decode/1) + end + + @spec decode(Absinthe.Blueprint.Input.String.t()) :: {:ok, term} | :error + @spec decode(Absinthe.Blueprint.Input.Null.t()) :: {:ok, nil} + defp decode(%Absinthe.Blueprint.Input.String{value: value}) do + if Tzdata.zone_exists?(value), + do: {:ok, value}, + else: {:error, dgettext("errors", "Timezone ID %{timezone} is invalid", timezone: value)} + end + + defp decode(%Absinthe.Blueprint.Input.Null{}) do + {:ok, nil} + end + + defp decode(_) do + :error + end + + defp encode(value), do: value +end diff --git a/lib/graphql/schema/event.ex b/lib/graphql/schema/event.ex index a44294ef..544f565d 100644 --- a/lib/graphql/schema/event.ex +++ b/lib/graphql/schema/event.ex @@ -250,7 +250,7 @@ defmodule Mobilizon.GraphQL.Schema.EventType do field(:show_start_time, :boolean, description: "Show event start time") field(:show_end_time, :boolean, description: "Show event end time") - field(:timezone, :string, description: "The event's timezone") + field(:timezone, :timezone, description: "The event's timezone") field(:hide_organizer_when_group_event, :boolean, description: @@ -303,7 +303,7 @@ defmodule Mobilizon.GraphQL.Schema.EventType do field(:show_start_time, :boolean, description: "Show event start time") field(:show_end_time, :boolean, description: "Show event end time") - field(:timezone, :string, description: "The event's timezone") + field(:timezone, :timezone, description: "The event's timezone") field(:hide_organizer_when_group_event, :boolean, description: diff --git a/lib/graphql/schema/events/participant.ex b/lib/graphql/schema/events/participant.ex index 6e61af84..457e5b14 100644 --- a/lib/graphql/schema/events/participant.ex +++ b/lib/graphql/schema/events/participant.ex @@ -96,7 +96,7 @@ defmodule Mobilizon.GraphQL.Schema.Events.ParticipantType do arg(:email, :string, description: "The anonymous participant's email") arg(:message, :string, description: "The anonymous participant's message") arg(:locale, :string, description: "The anonymous participant's locale") - arg(:timezone, :string, description: "The anonymous participant's timezone") + arg(:timezone, :timezone, description: "The anonymous participant's timezone") middleware(Rajska.QueryAuthorization, permit: :all, rule: :"write:participation") resolve(&Participant.actor_join_event/3) end diff --git a/lib/graphql/schema/user.ex b/lib/graphql/schema/user.ex index 9fc64053..5588a414 100644 --- a/lib/graphql/schema/user.ex +++ b/lib/graphql/schema/user.ex @@ -220,7 +220,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do """ object :user_settings do meta(:authorize, :user) - field(:timezone, :string, description: "The timezone for this user") + field(:timezone, :timezone, description: "The timezone for this user") field(:notification_on_day, :boolean, description: "Whether this user will receive an email at the start of the day of an event." @@ -450,7 +450,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do @desc "Set user settings" field :set_user_settings, :user_settings do - arg(:timezone, :string, description: "The timezone for this user") + arg(:timezone, :timezone, description: "The timezone for this user") arg(:notification_on_day, :boolean, description: