diff --git a/js/src/components/Event/ExternalParticipationButton.vue b/js/src/components/Event/ExternalParticipationButton.vue new file mode 100644 index 000000000..535194949 --- /dev/null +++ b/js/src/components/Event/ExternalParticipationButton.vue @@ -0,0 +1,27 @@ + + + diff --git a/js/src/graphql/event.ts b/js/src/graphql/event.ts index 605d9ddc3..e9f7682a7 100644 --- a/js/src/graphql/event.ts +++ b/js/src/graphql/event.ts @@ -21,6 +21,7 @@ const FULL_EVENT_FRAGMENT = gql` status visibility joinOptions + externalParticipationUrl draft language category @@ -121,6 +122,7 @@ export const FETCH_EVENT_BASIC = gql` id uuid joinOptions + externalParticipationUrl participantStats { going notApproved @@ -199,6 +201,7 @@ export const CREATE_EVENT = gql` $status: EventStatus $visibility: EventVisibility $joinOptions: EventJoinOptions + $externalParticipationUrl: String $draft: Boolean $tags: [String] $picture: MediaInput @@ -220,6 +223,7 @@ export const CREATE_EVENT = gql` status: $status visibility: $visibility joinOptions: $joinOptions + externalParticipationUrl: $externalParticipationUrl draft: $draft tags: $tags picture: $picture @@ -247,6 +251,7 @@ export const EDIT_EVENT = gql` $status: EventStatus $visibility: EventVisibility $joinOptions: EventJoinOptions + $externalParticipationUrl: String $draft: Boolean $tags: [String] $picture: MediaInput @@ -269,6 +274,7 @@ export const EDIT_EVENT = gql` status: $status visibility: $visibility joinOptions: $joinOptions + externalParticipationUrl: $externalParticipationUrl draft: $draft tags: $tags picture: $picture diff --git a/js/src/types/enums.ts b/js/src/types/enums.ts index 1061d196b..55732bd4e 100644 --- a/js/src/types/enums.ts +++ b/js/src/types/enums.ts @@ -64,6 +64,7 @@ export enum EventJoinOptions { FREE = "FREE", RESTRICTED = "RESTRICTED", INVITE = "INVITE", + EXTERNAL = "EXTERNAL", } export enum EventVisibilityJoinOptions { diff --git a/js/src/types/event.model.ts b/js/src/types/event.model.ts index e06703665..314d50c81 100644 --- a/js/src/types/event.model.ts +++ b/js/src/types/event.model.ts @@ -42,6 +42,7 @@ interface IEventEditJSON { status: EventStatus; visibility: EventVisibility; joinOptions: EventJoinOptions; + externalParticipationUrl: string | null; draft: boolean; picture?: IMedia | { mediaId: string } | null; attributedToId: string | null; @@ -71,6 +72,7 @@ export interface IEvent { status: EventStatus; visibility: EventVisibility; joinOptions: EventJoinOptions; + externalParticipationUrl: string | null; draft: boolean; picture: IMedia | null; @@ -131,6 +133,8 @@ export class EventModel implements IEvent { joinOptions = EventJoinOptions.FREE; + externalParticipationUrl: string | null = null; + status = EventStatus.CONFIRMED; draft = true; @@ -196,6 +200,7 @@ export class EventModel implements IEvent { this.status = hash.status; this.visibility = hash.visibility; this.joinOptions = hash.joinOptions; + this.externalParticipationUrl = hash.externalParticipationUrl; this.draft = hash.draft; this.picture = hash.picture; @@ -248,6 +253,7 @@ export function toEditJSON(event: IEditableEvent): IEventEditJSON { category: event.category, visibility: event.visibility, joinOptions: event.joinOptions, + externalParticipationUrl: event.externalParticipationUrl, draft: event.draft, tags: event.tags.map((t) => t.title), onlineAddress: event.onlineAddress, diff --git a/js/src/views/Event/Edit.vue b/js/src/views/Event/Edit.vue index 2240edf27..f26b73737 100644 --- a/js/src/views/Event/Edit.vue +++ b/js/src/views/Event/Edit.vue @@ -221,9 +221,33 @@ --> +
+ + + {{ + $t("I want to manage the registration with an external provider.") + }} + +
+ +
+ + + +
+
@@ -246,21 +270,21 @@
-
+
{{ $t("I want to approve every participation request") }}
-
+
{{ $t("Limited number of places") }}
-
+
{ return this.event.title.length > 80 ? ["is-info", this.$t("The event title will be ellipsed.") as string] diff --git a/js/src/views/Event/Event.vue b/js/src/views/Event/Event.vue old mode 100755 new mode 100644 index ad5cfc7da..e97cb2b6b --- a/js/src/views/Event/Event.vue +++ b/js/src/views/Event/Event.vue @@ -94,7 +94,13 @@
+ {{ organizer.domain }} -

+

Map.get("ical:status", "CONFIRMED") |> String.downcase(), @@ -129,6 +130,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do "mediaType" => "text/html", "startTime" => event.begins_on |> shift_tz(event.options.timezone) |> date_to_string(), "joinMode" => to_string(event.join_options), + "externalParticipationUrl" => event.external_participation_url, "endTime" => event.ends_on |> shift_tz(event.options.timezone) |> date_to_string(), "tag" => event.tags |> build_tags(), "maximumAttendeeCapacity" => event.options.maximum_attendee_capacity, diff --git a/lib/graphql/schema/event.ex b/lib/graphql/schema/event.ex index 9a4dd9ea3..2ed720cd7 100644 --- a/lib/graphql/schema/event.ex +++ b/lib/graphql/schema/event.ex @@ -30,6 +30,7 @@ defmodule Mobilizon.GraphQL.Schema.EventType do 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") + field(:external_participation_url, :string, description: "External URL for participation") field(:picture, :media, description: "The event's picture", @@ -123,6 +124,7 @@ defmodule Mobilizon.GraphQL.Schema.EventType do value(:free, description: "Anyone can join and is automatically accepted") value(:restricted, description: "Manual acceptation") value(:invite, description: "Participants must be invited") + value(:external, description: "External registration") end @desc "The list of possible options for the event's status" @@ -379,6 +381,8 @@ defmodule Mobilizon.GraphQL.Schema.EventType do description: "The event's options to join" ) + arg(:external_participation_url, :string, description: "External URL for participation") + arg(:tags, list_of(:string), default_value: [], description: "The list of tags associated to the event" @@ -439,6 +443,8 @@ defmodule Mobilizon.GraphQL.Schema.EventType do description: "The event's options to join" ) + arg(:external_participation_url, :string, description: "External URL for participation") + arg(:tags, list_of(:string), description: "The list of tags associated to the event") arg(:picture, :media_input, diff --git a/lib/mobilizon/events/event.ex b/lib/mobilizon/events/event.ex index f618e1ab2..4ef3247df 100644 --- a/lib/mobilizon/events/event.ex +++ b/lib/mobilizon/events/event.ex @@ -47,6 +47,7 @@ defmodule Mobilizon.Events.Event do draft: boolean, visibility: atom(), join_options: atom(), + external_participation_url: String.t(), publish_at: DateTime.t() | nil, uuid: Ecto.UUID.t(), online_address: String.t() | nil, @@ -81,6 +82,7 @@ defmodule Mobilizon.Events.Event do :local, :visibility, :join_options, + :external_participation_url, :publish_at, :online_address, :phone_address, @@ -105,6 +107,7 @@ defmodule Mobilizon.Events.Event do field(:draft, :boolean, default: false) field(:visibility, EventVisibility, default: :public) field(:join_options, JoinOptions, default: :free) + field(:external_participation_url, :string) field(:publish_at, :utc_datetime) field(:uuid, Ecto.UUID, default: Ecto.UUID.generate()) field(:online_address, :string) diff --git a/lib/mobilizon/events/events.ex b/lib/mobilizon/events/events.ex index 8287b4e9d..264a469f0 100644 --- a/lib/mobilizon/events/events.ex +++ b/lib/mobilizon/events/events.ex @@ -46,7 +46,8 @@ defmodule Mobilizon.Events do defenum(JoinOptions, :join_options, [ :free, :restricted, - :invite + :invite, + :external ]) defenum(EventStatus, :event_status, [ diff --git a/priv/repo/migrations/20211018230000_add_external_url_for_events.exs b/priv/repo/migrations/20211018230000_add_external_url_for_events.exs new file mode 100644 index 000000000..988f79c15 --- /dev/null +++ b/priv/repo/migrations/20211018230000_add_external_url_for_events.exs @@ -0,0 +1,21 @@ +defmodule Mobilizon.Storage.Repo.Migrations.AddExternalUrlForEvents do + use Ecto.Migration + alias Mobilizon.Events.JoinOptions + + def change do + alter table(:events) do + add(:external_participation_url, :string) + end + + execute("ALTER TABLE events ALTER COLUMN join_options TYPE VARCHAR USING join_options::text") + execute("ALTER TABLE events ALTER COLUMN join_options DROP DEFAULT") + JoinOptions.drop_type() + JoinOptions.create_type() + + execute( + "ALTER TABLE events ALTER COLUMN join_options TYPE join_options USING join_options::join_options" + ) + + execute("ALTER TABLE events ALTER COLUMN join_options SET DEFAULT 'free'::join_options") + end +end diff --git a/schema.graphql b/schema.graphql index 65907e253..4e920170e 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1551,6 +1551,9 @@ type RootMutationType { "The event's options to join" joinOptions: EventJoinOptions + "External URL for participation" + externalParticipationUrl: String + "The list of tags associated to the event" tags: [String] @@ -1620,6 +1623,9 @@ type RootMutationType { "The event's options to join" joinOptions: EventJoinOptions + "External URL for participation" + externalParticipationUrl: String + "The list of tags associated to the event" tags: [String] @@ -2962,6 +2968,9 @@ type Event implements ActivityObject & Interactable & ActionLogObject { "The event's visibility" joinOptions: EventJoinOptions + "External URL for participation" + externalParticipationUrl: String + "The event's picture" picture: Media @@ -3150,6 +3159,9 @@ enum EventJoinOptions { "Participants must be invited" INVITE + + "External registration" + EXTERNAL } type InstanceFeeds {