Send email notifications when a participation is approved/rejected
Also handles participant status :rejected instead of deleting the participation Closes #164 Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
d30b2fa147
commit
5b4f1c271a
@ -14,7 +14,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<footer class="card-footer">
|
||||
<b-button v-if="participant.role === ParticipantRole.NOT_APPROVED" @click="accept(participant)" type="is-success" class="card-footer-item">{{ $t('Approve') }}</b-button>
|
||||
<b-button v-if="[ParticipantRole.NOT_APPROVED, ParticipantRole.REJECTED].includes(participant.role)" @click="accept(participant)" type="is-success" class="card-footer-item">{{ $t('Approve') }}</b-button>
|
||||
<b-button v-if="participant.role === ParticipantRole.NOT_APPROVED" @click="reject(participant)" type="is-danger" class="card-footer-item">{{ $t('Reject')}} </b-button>
|
||||
<b-button v-if="participant.role === ParticipantRole.PARTICIPANT" @click="exclude(participant)" type="is-danger" class="card-footer-item">{{ $t('Exclude')}} </b-button>
|
||||
<span v-if="participant.role === ParticipantRole.CREATOR" class="card-footer-item">{{ $t('Creator')}} </span>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<div class="participation-button">
|
||||
<b-dropdown aria-role="list" position="is-bottom-left" v-if="participation && participation.role === ParticipantRole.PARTICIPANT">
|
||||
<button class="button is-success" type="button" slot="trigger">
|
||||
<b-icon icon="check"></b-icon>
|
||||
<template>
|
||||
<span>{{ $t('I participate') }}</span>
|
||||
</template>
|
||||
@ -12,7 +13,7 @@
|
||||
<!-- {{ $t('Change my identity…')}}-->
|
||||
<!-- </b-dropdown-item>-->
|
||||
|
||||
<b-dropdown-item :value="false" aria-role="listitem" @click="confirmLeave">
|
||||
<b-dropdown-item :value="false" aria-role="listitem" @click="confirmLeave" class="has-text-danger">
|
||||
{{ $t('Cancel my participation…')}}
|
||||
</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
@ -20,6 +21,7 @@
|
||||
<div v-else-if="participation && participation.role === ParticipantRole.NOT_APPROVED">
|
||||
<b-dropdown aria-role="list" position="is-bottom-left" class="dropdown-disabled">
|
||||
<button class="button is-success" type="button" slot="trigger">
|
||||
<b-icon icon="timer-sand-empty"></b-icon>
|
||||
<template>
|
||||
<span>{{ $t('I participate') }}</span>
|
||||
</template>
|
||||
@ -30,7 +32,7 @@
|
||||
<!-- {{ $t('Change my identity…')}}-->
|
||||
<!-- </b-dropdown-item>-->
|
||||
|
||||
<b-dropdown-item :value="false" aria-role="listitem" @click="confirmLeave">
|
||||
<b-dropdown-item :value="false" aria-role="listitem" @click="confirmLeave" class="has-text-danger">
|
||||
{{ $t('Cancel my participation request…')}}
|
||||
</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
@ -38,6 +40,10 @@
|
||||
<small>{{ $t('Waiting for organization team approval.')}}</small>
|
||||
</div>
|
||||
|
||||
<div v-else-if="participation && participation.role === ParticipantRole.REJECTED">
|
||||
<span>{{ $t('Unfortunately, your participation request was rejected by the organizers.')}}</span>
|
||||
</div>
|
||||
|
||||
<b-dropdown aria-role="list" position="is-bottom-left" v-if="!participation">
|
||||
<button class="button is-primary" type="button" slot="trigger">
|
||||
<template>
|
||||
|
@ -334,23 +334,15 @@ export const LEAVE_EVENT = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export const ACCEPT_PARTICIPANT = gql`
|
||||
mutation AcceptParticipant($id: ID!, $moderatorActorId: ID!) {
|
||||
acceptParticipation(id: $id, moderatorActorId: $moderatorActorId) {
|
||||
export const UPDATE_PARTICIPANT = gql`
|
||||
mutation AcceptParticipant($id: ID!, $moderatorActorId: ID!, $role: ParticipantRoleEnum!) {
|
||||
updateParticipation(id: $id, moderatorActorId: $moderatorActorId, role: $role) {
|
||||
role,
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const REJECT_PARTICIPANT = gql`
|
||||
mutation RejectParticipant($id: ID!, $moderatorActorId: ID!) {
|
||||
rejectParticipation(id: $id, moderatorActorId: $moderatorActorId) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const DELETE_EVENT = gql`
|
||||
mutation DeleteEvent($eventId: ID!, $actorId: ID!) {
|
||||
deleteEvent(
|
||||
@ -371,7 +363,8 @@ export const PARTICIPANTS = gql`
|
||||
},
|
||||
participantStats {
|
||||
approved,
|
||||
unapproved
|
||||
unapproved,
|
||||
rejected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -253,5 +253,9 @@
|
||||
"{approved} / {total} seats": "{approved} / {total} seats",
|
||||
"{count} participants": "{count} participants",
|
||||
"{count} requests waiting": "{count} requests waiting",
|
||||
"© The Mobilizon Contributors {date} - Made with Elixir, Phoenix, VueJS & with some love and some weeks": "© The Mobilizon Contributors {date} - Made with Elixir, Phoenix, VueJS & with some love and some weeks"
|
||||
"© The Mobilizon Contributors {date} - Made with Elixir, Phoenix, VueJS & with some love and some weeks": "© The Mobilizon Contributors {date} - Made with Elixir, Phoenix, VueJS & with some love and some weeks",
|
||||
"Requests": "Requests",
|
||||
"Rejected": "Rejected",
|
||||
"Rejected participations": "Rejected participations",
|
||||
"Unfortunately, your participation request was rejected by the organizers.": "Unfortunately, your participation request was rejected by the organizers."
|
||||
}
|
@ -253,5 +253,9 @@
|
||||
"{approved} / {total} seats": "{approved} / {total} places",
|
||||
"{count} participants": "Un⋅e participant⋅e|{count} participant⋅e⋅s",
|
||||
"{count} requests waiting": "Un⋅e demande en attente|{count} demandes en attente",
|
||||
"© The Mobilizon Contributors {date} - Made with Elixir, Phoenix, VueJS & with some love and some weeks": "© Les contributeurs de Mobilizon {date} - Fait avec Elixir, Phoenix, VueJS & et de l'amour et des semaines"
|
||||
"© The Mobilizon Contributors {date} - Made with Elixir, Phoenix, VueJS & with some love and some weeks": "© Les contributeurs de Mobilizon {date} - Fait avec Elixir, Phoenix, VueJS & et de l'amour et des semaines",
|
||||
"Requests": "Requêtes",
|
||||
"Rejected": "Rejetés",
|
||||
"Rejected participations": "Participations rejetées",
|
||||
"Unfortunately, your participation request was rejected by the organizers.": "Malheureusement, votre demande de participation a été refusée par les organisateur⋅ices."
|
||||
}
|
@ -30,6 +30,7 @@ export enum EventVisibilityJoinOptions {
|
||||
|
||||
export enum ParticipantRole {
|
||||
NOT_APPROVED = 'NOT_APPROVED',
|
||||
REJECTED = 'REJECTED',
|
||||
PARTICIPANT = 'PARTICIPANT',
|
||||
MODERATOR = 'MODERATOR',
|
||||
ADMINISTRATOR = 'ADMINISTRATOR',
|
||||
@ -112,6 +113,7 @@ export interface IEvent {
|
||||
participantStats: {
|
||||
approved: number;
|
||||
unapproved: number;
|
||||
rejected: number;
|
||||
};
|
||||
participants: IParticipant[];
|
||||
|
||||
@ -175,7 +177,7 @@ export class EventModel implements IEvent {
|
||||
|
||||
publishAt = new Date();
|
||||
|
||||
participantStats = { approved: 0, unapproved: 0 };
|
||||
participantStats = { approved: 0, unapproved: 0, rejected: 0 };
|
||||
participants: IParticipant[] = [];
|
||||
|
||||
relatedEvents: IEvent[] = [];
|
||||
|
@ -4,7 +4,7 @@
|
||||
<b-tab-item>
|
||||
<template slot="header">
|
||||
<b-icon icon="information-outline"></b-icon>
|
||||
<span> Participants <b-tag rounded> {{ participantStats.approved }} </b-tag> </span>
|
||||
<span>{{ $t('Participants')}} <b-tag rounded> {{ participantStats.approved }} </b-tag> </span>
|
||||
</template>
|
||||
<section v-if="participantsAndCreators.length > 0">
|
||||
<h2 class="title">{{ $t('Participants') }}</h2>
|
||||
@ -23,7 +23,7 @@
|
||||
<b-tab-item>
|
||||
<template slot="header">
|
||||
<b-icon icon="source-pull"></b-icon>
|
||||
<span> Demandes <b-tag rounded> {{ participantStats.unapproved }} </b-tag> </span>
|
||||
<span>{{ $t('Requests') }} <b-tag rounded> {{ participantStats.unapproved }} </b-tag> </span>
|
||||
</template>
|
||||
<section v-if="queue.length > 0">
|
||||
<h2 class="title">{{ $t('Waiting list') }}</h2>
|
||||
@ -39,6 +39,25 @@
|
||||
</div>
|
||||
</section>
|
||||
</b-tab-item>
|
||||
<b-tab-item>
|
||||
<template slot="header">
|
||||
<b-icon icon="source-pull"></b-icon>
|
||||
<span>{{ $t('Rejected')}} <b-tag rounded> {{ participantStats.rejected }} </b-tag> </span>
|
||||
</template>
|
||||
<section v-if="rejected.length > 0">
|
||||
<h2 class="title">{{ $t('Rejected participations') }}</h2>
|
||||
<div class="columns">
|
||||
<div class="column is-one-quarter-desktop" v-for="participant in rejected" :key="participant.actor.id">
|
||||
<participant-card
|
||||
:participant="participant"
|
||||
:accept="acceptParticipant"
|
||||
:reject="refuseParticipant"
|
||||
:exclude="refuseParticipant"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</b-tab-item>
|
||||
</b-tabs>
|
||||
</main>
|
||||
</template>
|
||||
@ -46,7 +65,7 @@
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
import { IEvent, IParticipant, Participant, ParticipantRole } from '@/types/event.model';
|
||||
import { ACCEPT_PARTICIPANT, PARTICIPANTS, REJECT_PARTICIPANT } from '@/graphql/event';
|
||||
import { UPDATE_PARTICIPANT, PARTICIPANTS } from '@/graphql/event';
|
||||
import ParticipantCard from '@/components/Account/ParticipantCard.vue';
|
||||
import { CURRENT_ACTOR_CLIENT } from '@/graphql/actor';
|
||||
import { IPerson } from '@/types/actor';
|
||||
@ -98,6 +117,19 @@ import { IPerson } from '@/types/actor';
|
||||
},
|
||||
update: data => data.event.participants.map(participation => new Participant(participation)),
|
||||
},
|
||||
rejected: {
|
||||
query: PARTICIPANTS,
|
||||
variables() {
|
||||
return {
|
||||
uuid: this.eventId,
|
||||
page: 1,
|
||||
limit: 20,
|
||||
roles: [ParticipantRole.REJECTED].join(),
|
||||
actorId: this.currentActor.id,
|
||||
};
|
||||
},
|
||||
update: data => data.event.participants.map(participation => new Participant(participation)),
|
||||
},
|
||||
},
|
||||
})
|
||||
export default class Participants extends Vue {
|
||||
@ -108,6 +140,7 @@ export default class Participants extends Vue {
|
||||
// participants: IParticipant[] = [];
|
||||
organizers: IParticipant[] = [];
|
||||
queue: IParticipant[] = [];
|
||||
rejected: IParticipant[] = [];
|
||||
event!: IEvent;
|
||||
|
||||
ParticipantRole = ParticipantRole;
|
||||
@ -156,15 +189,16 @@ export default class Participants extends Vue {
|
||||
async acceptParticipant(participant: IParticipant) {
|
||||
try {
|
||||
const { data } = await this.$apollo.mutate({
|
||||
mutation: ACCEPT_PARTICIPANT,
|
||||
mutation: UPDATE_PARTICIPANT,
|
||||
variables: {
|
||||
id: participant.id,
|
||||
moderatorActorId: this.currentActor.id,
|
||||
role: ParticipantRole.PARTICIPANT,
|
||||
},
|
||||
});
|
||||
if (data) {
|
||||
console.log('accept', data);
|
||||
this.queue.filter(participant => participant !== data.acceptParticipation.id);
|
||||
this.queue.filter(participant => participant !== data.updateParticipation.id);
|
||||
this.rejected.filter(participant => participant !== data.updateParticipation.id);
|
||||
this.participants.push(participant);
|
||||
}
|
||||
} catch (e) {
|
||||
@ -175,15 +209,17 @@ export default class Participants extends Vue {
|
||||
async refuseParticipant(participant: IParticipant) {
|
||||
try {
|
||||
const { data } = await this.$apollo.mutate({
|
||||
mutation: REJECT_PARTICIPANT,
|
||||
mutation: UPDATE_PARTICIPANT,
|
||||
variables: {
|
||||
id: participant.id,
|
||||
moderatorActorId: this.currentActor.id,
|
||||
role: ParticipantRole.REJECTED,
|
||||
},
|
||||
});
|
||||
if (data) {
|
||||
this.participants.filter(participant => participant !== data.rejectParticipation.id);
|
||||
this.queue.filter(participant => participant !== data.rejectParticipation.id);
|
||||
this.participants.filter(participant => participant !== data.updateParticipation.id);
|
||||
this.queue.filter(participant => participant !== data.updateParticipation.id);
|
||||
this.rejected.push(participant);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
@ -70,6 +70,7 @@ defmodule Mobilizon.Events do
|
||||
|
||||
defenum(ParticipantRole, :participant_role, [
|
||||
:not_approved,
|
||||
:rejected,
|
||||
:participant,
|
||||
:moderator,
|
||||
:administrator,
|
||||
@ -718,6 +719,17 @@ defmodule Mobilizon.Events do
|
||||
|> Repo.aggregate(:count, :id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Counts rejected participants.
|
||||
"""
|
||||
@spec count_rejected_participants(integer | String.t()) :: integer
|
||||
def count_rejected_participants(event_id) do
|
||||
event_id
|
||||
|> count_participants_query()
|
||||
|> filter_rejected_role()
|
||||
|> Repo.aggregate(:count, :id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets the default participant role depending on the event join options.
|
||||
"""
|
||||
@ -1361,7 +1373,7 @@ defmodule Mobilizon.Events do
|
||||
|
||||
@spec filter_approved_role(Ecto.Query.t()) :: Ecto.Query.t()
|
||||
defp filter_approved_role(query) do
|
||||
from(p in query, where: p.role != ^:not_approved)
|
||||
from(p in query, where: p.role not in ^[:not_approved, :rejected])
|
||||
end
|
||||
|
||||
@spec filter_unapproved_role(Ecto.Query.t()) :: Ecto.Query.t()
|
||||
@ -1369,6 +1381,11 @@ defmodule Mobilizon.Events do
|
||||
from(p in query, where: p.role == ^:not_approved)
|
||||
end
|
||||
|
||||
@spec filter_rejected_role(Ecto.Query.t()) :: Ecto.Query.t()
|
||||
defp filter_rejected_role(query) do
|
||||
from(p in query, where: p.role == ^:rejected)
|
||||
end
|
||||
|
||||
@spec filter_role(Ecto.Query.t(), list(atom())) :: Ecto.Query.t()
|
||||
defp filter_role(query, []), do: query
|
||||
|
||||
|
@ -7,6 +7,7 @@ defmodule MobilizonWeb.API.Participations do
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.Service.ActivityPub
|
||||
alias MobilizonWeb.Email.Participation
|
||||
|
||||
@spec join(Event.t(), Actor.t()) :: {:ok, Participant.t()}
|
||||
def join(%Event{id: event_id} = event, %Actor{id: actor_id} = actor) do
|
||||
@ -22,10 +23,19 @@ defmodule MobilizonWeb.API.Participations do
|
||||
end
|
||||
end
|
||||
|
||||
def accept(
|
||||
%Participant{} = participation,
|
||||
%Actor{} = moderator
|
||||
) do
|
||||
@doc """
|
||||
Update participation status
|
||||
"""
|
||||
def update(%Participant{} = participation, %Actor{} = moderator, :participant),
|
||||
do: accept(participation, moderator)
|
||||
|
||||
def update(%Participant{} = participation, %Actor{} = moderator, :rejected),
|
||||
do: reject(participation, moderator)
|
||||
|
||||
defp accept(
|
||||
%Participant{} = participation,
|
||||
%Actor{} = moderator
|
||||
) do
|
||||
with {:ok, activity, _} <-
|
||||
ActivityPub.accept(
|
||||
%{
|
||||
@ -36,15 +46,16 @@ defmodule MobilizonWeb.API.Participations do
|
||||
"#{MobilizonWeb.Endpoint.url()}/accept/join/#{participation.id}"
|
||||
),
|
||||
{:ok, %Participant{role: :participant} = participation} <-
|
||||
Events.update_participant(participation, %{"role" => :participant}) do
|
||||
Events.update_participant(participation, %{"role" => :participant}),
|
||||
:ok <- Participation.send_emails_to_local_user(participation) do
|
||||
{:ok, activity, participation}
|
||||
end
|
||||
end
|
||||
|
||||
def reject(
|
||||
%Participant{} = participation,
|
||||
%Actor{} = moderator
|
||||
) do
|
||||
defp reject(
|
||||
%Participant{} = participation,
|
||||
%Actor{} = moderator
|
||||
) do
|
||||
with {:ok, activity, _} <-
|
||||
ActivityPub.reject(
|
||||
%{
|
||||
@ -54,8 +65,9 @@ defmodule MobilizonWeb.API.Participations do
|
||||
},
|
||||
"#{MobilizonWeb.Endpoint.url()}/reject/join/#{participation.id}"
|
||||
),
|
||||
{:ok, %Participant{} = participation} <-
|
||||
Events.delete_participant(participation) do
|
||||
{:ok, %Participant{role: :rejected} = participation} <-
|
||||
Events.update_participant(participation, %{"role" => :rejected}),
|
||||
:ok <- Participation.send_emails_to_local_user(participation) do
|
||||
{:ok, activity, participation}
|
||||
end
|
||||
end
|
||||
|
84
lib/mobilizon_web/email/participation.ex
Normal file
84
lib/mobilizon_web/email/participation.ex
Normal file
@ -0,0 +1,84 @@
|
||||
defmodule MobilizonWeb.Email.Participation do
|
||||
@moduledoc """
|
||||
Handles emails sent about participation.
|
||||
"""
|
||||
|
||||
use Bamboo.Phoenix, view: MobilizonWeb.EmailView
|
||||
|
||||
import Bamboo.Phoenix
|
||||
|
||||
import MobilizonWeb.Gettext
|
||||
|
||||
alias Mobilizon.Users.User
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events.Participant
|
||||
|
||||
alias MobilizonWeb.Email
|
||||
|
||||
@doc """
|
||||
Send emails to local user
|
||||
"""
|
||||
def send_emails_to_local_user(
|
||||
%Participant{actor: %Actor{user_id: nil} = _actor} = _participation
|
||||
),
|
||||
do: :ok
|
||||
|
||||
@doc """
|
||||
Send emails to local user
|
||||
"""
|
||||
def send_emails_to_local_user(
|
||||
%Participant{actor: %Actor{user_id: user_id} = _actor} = participation
|
||||
) do
|
||||
with %User{} = user <- Mobilizon.Users.get_user!(user_id) do
|
||||
user
|
||||
|> participation_updated(participation)
|
||||
|> Email.Mailer.deliver_later()
|
||||
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
||||
@spec participation_updated(User.t(), Participant.t(), String.t()) :: Bamboo.Email.t()
|
||||
def participation_updated(user, participant, locale \\ "en")
|
||||
|
||||
def participation_updated(
|
||||
%User{email: email},
|
||||
%Participant{event: event, role: :rejected},
|
||||
locale
|
||||
) do
|
||||
Gettext.put_locale(locale)
|
||||
|
||||
subject =
|
||||
gettext(
|
||||
"Your participation to event %{title} has been rejected",
|
||||
title: event.title
|
||||
)
|
||||
|
||||
Email.base_email(to: email, subject: subject)
|
||||
|> assign(:locale, locale)
|
||||
|> assign(:event, event)
|
||||
|> assign(:subject, subject)
|
||||
|> render(:event_participation_rejected)
|
||||
end
|
||||
|
||||
@spec participation_updated(User.t(), Participant.t(), String.t()) :: Bamboo.Email.t()
|
||||
def participation_updated(
|
||||
%User{email: email},
|
||||
%Participant{event: event, role: :participant},
|
||||
locale
|
||||
) do
|
||||
Gettext.put_locale(locale)
|
||||
|
||||
subject =
|
||||
gettext(
|
||||
"Your participation to event %{title} has been approved",
|
||||
title: event.title
|
||||
)
|
||||
|
||||
Email.base_email(to: email, subject: subject)
|
||||
|> assign(:locale, locale)
|
||||
|> assign(:event, event)
|
||||
|> assign(:subject, subject)
|
||||
|> render(:event_participation_approved)
|
||||
end
|
||||
end
|
@ -83,7 +83,8 @@ defmodule MobilizonWeb.Resolvers.Event do
|
||||
{:ok,
|
||||
%{
|
||||
approved: Mobilizon.Events.count_approved_participants(id),
|
||||
unapproved: Mobilizon.Events.count_unapproved_participants(id)
|
||||
unapproved: Mobilizon.Events.count_unapproved_participants(id),
|
||||
rejected: Mobilizon.Events.count_rejected_participants(id)
|
||||
}}
|
||||
end
|
||||
|
||||
@ -202,9 +203,9 @@ defmodule MobilizonWeb.Resolvers.Event do
|
||||
{:error, "You need to be logged-in to leave an event"}
|
||||
end
|
||||
|
||||
def accept_participation(
|
||||
def update_participation(
|
||||
_parent,
|
||||
%{id: participation_id, moderator_actor_id: moderator_actor_id},
|
||||
%{id: participation_id, moderator_actor_id: moderator_actor_id, role: new_role},
|
||||
%{
|
||||
context: %{
|
||||
current_user: user
|
||||
@ -214,14 +215,15 @@ defmodule MobilizonWeb.Resolvers.Event do
|
||||
# Check that moderator provided is rightly authenticated
|
||||
with {:is_owned, moderator_actor} <- User.owns_actor(user, moderator_actor_id),
|
||||
# Check that participation already exists
|
||||
{:has_participation, %Participant{role: :not_approved} = participation} <-
|
||||
{:has_participation, %Participant{role: old_role} = participation} <-
|
||||
{:has_participation, Mobilizon.Events.get_participant(participation_id)},
|
||||
{:same_role, false} <- {:same_role, new_role == old_role},
|
||||
# Check that moderator has right
|
||||
{:actor_approve_permission, true} <-
|
||||
{:actor_approve_permission,
|
||||
Mobilizon.Events.moderator_for_event?(participation.event.id, moderator_actor_id)},
|
||||
{:ok, _activity, participation} <-
|
||||
MobilizonWeb.API.Participations.accept(participation, moderator_actor) do
|
||||
MobilizonWeb.API.Participations.update(participation, moderator_actor, new_role) do
|
||||
{:ok, participation}
|
||||
else
|
||||
{:is_owned, nil} ->
|
||||
@ -234,55 +236,14 @@ defmodule MobilizonWeb.Resolvers.Event do
|
||||
{:actor_approve_permission, _} ->
|
||||
{:error, "Provided moderator actor ID doesn't have permission on this event"}
|
||||
|
||||
{:same_role, true} ->
|
||||
{:error, "Participant already has role #{new_role}"}
|
||||
|
||||
{:error, :participant_not_found} ->
|
||||
{:error, "Participant not found"}
|
||||
end
|
||||
end
|
||||
|
||||
def reject_participation(
|
||||
_parent,
|
||||
%{id: participation_id, moderator_actor_id: moderator_actor_id},
|
||||
%{
|
||||
context: %{
|
||||
current_user: user
|
||||
}
|
||||
}
|
||||
) do
|
||||
# Check that moderator provided is rightly authenticated
|
||||
with {:is_owned, moderator_actor} <- User.owns_actor(user, moderator_actor_id),
|
||||
# Check that participation really exists
|
||||
{:has_participation, %Participant{} = participation} <-
|
||||
{:has_participation, Mobilizon.Events.get_participant(participation_id)},
|
||||
# Check that moderator has right
|
||||
{:actor_approve_permission, true} <-
|
||||
{:actor_approve_permission,
|
||||
Mobilizon.Events.moderator_for_event?(participation.event.id, moderator_actor_id)},
|
||||
{:ok, _activity, participation} <-
|
||||
MobilizonWeb.API.Participations.reject(participation, moderator_actor) do
|
||||
{
|
||||
:ok,
|
||||
%{
|
||||
id: participation.id,
|
||||
event: %{
|
||||
id: participation.event.id
|
||||
},
|
||||
actor: %{
|
||||
id: participation.actor.id
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{:is_owned, nil} ->
|
||||
{:error, "Moderator Actor ID is not owned by authenticated user"}
|
||||
|
||||
{:actor_approve_permission, _} ->
|
||||
{:error, "Provided moderator actor ID doesn't have permission on this event"}
|
||||
|
||||
{:has_participation, nil} ->
|
||||
{:error, "Participant not found"}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Create an event
|
||||
"""
|
||||
|
@ -111,6 +111,7 @@ defmodule MobilizonWeb.Schema.EventType do
|
||||
object :participant_stats do
|
||||
field(:approved, :integer, description: "The number of approved participants")
|
||||
field(:unapproved, :integer, description: "The number of unapproved participants")
|
||||
field(:rejected, :integer, description: "The number of rejected participants")
|
||||
end
|
||||
|
||||
object :event_offer do
|
||||
|
@ -38,6 +38,7 @@ defmodule MobilizonWeb.Schema.Events.ParticipantType do
|
||||
value(:moderator)
|
||||
value(:administrator)
|
||||
value(:creator)
|
||||
value(:rejected)
|
||||
end
|
||||
|
||||
@desc "Represents a deleted participant"
|
||||
@ -65,19 +66,12 @@ defmodule MobilizonWeb.Schema.Events.ParticipantType do
|
||||
end
|
||||
|
||||
@desc "Accept a participation"
|
||||
field :accept_participation, :participant do
|
||||
field :update_participation, :participant do
|
||||
arg(:id, non_null(:id))
|
||||
arg(:role, non_null(:participant_role_enum))
|
||||
arg(:moderator_actor_id, non_null(:id))
|
||||
|
||||
resolve(&Resolvers.Event.accept_participation/3)
|
||||
end
|
||||
|
||||
@desc "Reject a participation"
|
||||
field :reject_participation, :deleted_participant do
|
||||
arg(:id, non_null(:id))
|
||||
arg(:moderator_actor_id, non_null(:id))
|
||||
|
||||
resolve(&Resolvers.Event.reject_participation/3)
|
||||
resolve(&Resolvers.Event.update_participation/3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -0,0 +1,81 @@
|
||||
<!-- HERO -->
|
||||
<tr>
|
||||
<td bgcolor="#424056" align="center" style="padding: 0px 10px 0px 10px;">
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="0" width="600">
|
||||
<tr>
|
||||
<td align="center" valign="top" width="600">
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; letter-spacing: 4px; line-height: 48px;">
|
||||
<h1 style="font-size: 48px; font-weight: 400; margin: 0;">
|
||||
<%= gettext "All good!" %>
|
||||
</h1>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
<!-- COPY BLOCK -->
|
||||
<tr>
|
||||
<td bgcolor="#f4f4f4" align="center" style="padding: 0px 10px 0px 10px;">
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="0" width="600">
|
||||
<tr>
|
||||
<td align="center" valign="top" width="600">
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<!-- COPY -->
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left" style="padding: 20px 30px 0px 30px; color: #666666; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;" >
|
||||
<p style="margin: 0;">
|
||||
<%= gettext "You requested to participate in event %{title}", title: @event.title %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left" style="padding: 20px 30px 40px 30px; color: #777777; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;" >
|
||||
<p style="margin: 0">
|
||||
<%= gettext "An organizer just approved your participation. You're now going to this event!" %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- BULLETPROOF BUTTON -->
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left">
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="center" style="padding: 20px 30px 60px 30px;">
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#424056"><a href="<%= page_url(MobilizonWeb.Endpoint, :event, @event.id) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #424056; display: inline-block;">
|
||||
<%= gettext "Go to event page" %>
|
||||
</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left" style="padding: 20px 30px 40px 30px; color: #777777; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: 400; line-height: 20px;" >
|
||||
<p style="margin: 0">
|
||||
<%= gettext "If you need to cancel your participation, just access the event page through link above and click on the participation button." %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
@ -0,0 +1,11 @@
|
||||
<%= gettext "Participation approved" %>
|
||||
|
||||
==
|
||||
|
||||
<%= gettext "You requested to participate in event %{title}.", title: @event.title %>
|
||||
|
||||
<%= gettext "An organizer just approved your participation. You're now going to this event!" %>
|
||||
|
||||
<%= page_url(MobilizonWeb.Endpoint, :event, @event.id) %>
|
||||
|
||||
<%= gettext "If you need to cancel your participation, just access the previous link and click on the participation button." %>
|
@ -0,0 +1,56 @@
|
||||
<!-- HERO -->
|
||||
<tr>
|
||||
<td bgcolor="#424056" align="center" style="padding: 0px 10px 0px 10px;">
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="0" width="600">
|
||||
<tr>
|
||||
<td align="center" valign="top" width="600">
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; letter-spacing: 4px; line-height: 48px;">
|
||||
<h1 style="font-size: 48px; font-weight: 400; margin: 0;">
|
||||
<%= gettext "Sorry!" %>
|
||||
</h1>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
<!-- COPY BLOCK -->
|
||||
<tr>
|
||||
<td bgcolor="#f4f4f4" align="center" style="padding: 0px 10px 0px 10px;">
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="0" width="600">
|
||||
<tr>
|
||||
<td align="center" valign="top" width="600">
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<!-- COPY -->
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left" style="padding: 20px 30px 0px 30px; color: #666666; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;" >
|
||||
<p style="margin: 0;">
|
||||
<%= gettext "You requested to participate in event %{title}", title: @event.title %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left" style="padding: 20px 30px 40px 30px; color: #777777; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;" >
|
||||
<p style="margin: 0">
|
||||
<%= gettext "Unfortunately, the organizers rejected your participation." %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
@ -0,0 +1,7 @@
|
||||
<%= gettext "Participation rejected" %>
|
||||
|
||||
==
|
||||
|
||||
<%= gettext "You requested to participate in event %{title}.", title: @event.title %>
|
||||
|
||||
<%= gettext "Unfortunately, the organizers rejected your participation." %>
|
@ -8,7 +8,6 @@ defmodule Mobilizon.Service.ActivityPub.Activity do
|
||||
local: boolean,
|
||||
actor: Actor.t(),
|
||||
recipients: [String.t()]
|
||||
# notifications: [???]
|
||||
}
|
||||
|
||||
defstruct [
|
||||
@ -16,6 +15,5 @@ defmodule Mobilizon.Service.ActivityPub.Activity do
|
||||
:local,
|
||||
:actor,
|
||||
:recipients
|
||||
# :notifications
|
||||
]
|
||||
end
|
||||
|
@ -454,7 +454,8 @@ defmodule Mobilizon.Service.ActivityPub do
|
||||
{:only_organizer, Participant.is_not_only_organizer(event_id, actor_id)},
|
||||
{:ok, %Participant{} = participant} <-
|
||||
Mobilizon.Events.get_participant(event_id, actor_id),
|
||||
{:ok, %Participant{} = participant} <- Mobilizon.Events.delete_participant(participant),
|
||||
{:ok, %Participant{} = participant} <-
|
||||
Events.delete_participant(participant),
|
||||
leave_data <- %{
|
||||
"type" => "Leave",
|
||||
# If it's an exclusion it should be something else
|
||||
|
@ -14,6 +14,7 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
|
||||
alias Mobilizon.Events.{Comment, Event, Participant}
|
||||
alias Mobilizon.Service.ActivityPub
|
||||
alias Mobilizon.Service.ActivityPub.{Converter, Convertible, Utils, Visibility}
|
||||
alias MobilizonWeb.Email.Participation
|
||||
|
||||
require Logger
|
||||
|
||||
@ -543,10 +544,8 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Handle incoming `Accept` activities wrapping a `Join` activity on an event
|
||||
"""
|
||||
def do_handle_incoming_accept_join(join_object, %Actor{} = actor_accepting) do
|
||||
# Handle incoming `Accept` activities wrapping a `Join` activity on an event
|
||||
defp do_handle_incoming_accept_join(join_object, %Actor{} = actor_accepting) do
|
||||
with {:join_event,
|
||||
{:ok,
|
||||
%Participant{role: :not_approved, actor: actor, id: join_id, event: event} =
|
||||
@ -566,7 +565,9 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
|
||||
"#{MobilizonWeb.Endpoint.url()}/accept/join/#{join_id}"
|
||||
),
|
||||
{:ok, %Participant{role: :participant}} <-
|
||||
Events.update_participant(participant, %{"role" => :participant}) do
|
||||
Events.update_participant(participant, %{"role" => :participant}),
|
||||
:ok <-
|
||||
Participation.send_emails_to_local_user(participant) do
|
||||
{:ok, activity, participant}
|
||||
else
|
||||
{:join_event, {:ok, %Participant{role: :participant}}} ->
|
||||
@ -591,10 +592,8 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Handle incoming `Reject` activities wrapping a `Join` activity on an event
|
||||
"""
|
||||
def do_handle_incoming_reject_join(join_object, %Actor{} = actor_accepting) do
|
||||
# Handle incoming `Reject` activities wrapping a `Join` activity on an event
|
||||
defp do_handle_incoming_reject_join(join_object, %Actor{} = actor_accepting) do
|
||||
with {:join_event,
|
||||
{:ok,
|
||||
%Participant{role: :not_approved, actor: actor, id: join_id, event: event} =
|
||||
@ -613,8 +612,9 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
|
||||
},
|
||||
"#{MobilizonWeb.Endpoint.url()}/reject/join/#{join_id}"
|
||||
),
|
||||
{:ok, %Participant{}} <-
|
||||
Events.delete_participant(participant) do
|
||||
{:ok, %Participant{role: :rejected} = participant} <-
|
||||
Events.update_participant(participant, %{"role" => :rejected}),
|
||||
:ok <- Participation.send_emails_to_local_user(participant) do
|
||||
{:ok, activity, participant}
|
||||
else
|
||||
{:join_event, {:ok, %Participant{role: :participant}}} ->
|
||||
|
@ -12,129 +12,231 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Translate Toolkit 2.4.0\n"
|
||||
|
||||
#: lib/mobilizon_web/templates/email/email.text.eex:3
|
||||
#, elixir-format
|
||||
msgid "An email sent by Mobilizon on %{instance}."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:48
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/password_reset.text.eex:12
|
||||
msgid "If you didn't request this, please ignore this email. Your password won't change until you access the link below and create a new one."
|
||||
msgstr ""
|
||||
|
||||
#: lib/service/export/feed.ex:161
|
||||
#, elixir-format
|
||||
#: lib/service/export/feed.ex:169
|
||||
msgid "Feed for %{email} on Mobilizon"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:122
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:122
|
||||
#: lib/mobilizon_web/templates/email/email.text.eex:6
|
||||
msgid "%{instance} is a Mobilizon server."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:38
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:38
|
||||
msgid "%{reporter_name} (%{reporter_username}) reported the following content."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:48
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:48
|
||||
msgid "%{title} by %{creator}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:58
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:58
|
||||
msgid "Activate my account"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:91
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:94
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:91
|
||||
msgid "Ask the community on Framacolibri"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:62
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:62
|
||||
#: lib/mobilizon_web/templates/email/report.text.eex:11
|
||||
msgid "Comments"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:46
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:46
|
||||
#: lib/mobilizon_web/templates/email/report.text.eex:6
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:45
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:45
|
||||
msgid "If you didn't request this, please ignore this email."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/email/user.ex:46
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/email/user.ex:45
|
||||
msgid "Instructions to reset your password on %{instance}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:123
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:123
|
||||
msgid "Learn more about Mobilizon."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:13
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:13
|
||||
msgid "Nearly here!"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:88
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:91
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:88
|
||||
msgid "Need some help? Something not working properly?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:13
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:13
|
||||
msgid "New report on %{instance}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:80
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:80
|
||||
#: lib/mobilizon_web/templates/email/report.text.eex:18
|
||||
msgid "Reason"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:61
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:61
|
||||
msgid "Reset Password"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:41
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:41
|
||||
msgid "Resetting your password is easy. Just press the button below and follow the instructions. We'll have you up and running in no time."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:13
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:13
|
||||
msgid "Trouble signing in?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:100
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:100
|
||||
msgid "View the report"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:38
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:38
|
||||
msgid "You created an account on %{host} with this email address. You are one click away from activating it."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:38
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:38
|
||||
msgid "You requested a new password for your account on %{server}."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/email/user.ex:25
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/email/user.ex:25
|
||||
msgid "Instructions to confirm your Mobilizon account on %{instance}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/email/admin.ex:23
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/email/admin.ex:23
|
||||
msgid "New report on Mobilizon instance %{instance}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.text.eex:1
|
||||
msgid "Activate your account"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/event_participation_approved.html.eex:13
|
||||
msgid "All good!"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/event_participation_approved.html.eex:45
|
||||
#: lib/mobilizon_web/templates/email/event_participation_approved.text.eex:7
|
||||
msgid "An organizer just approved your participation. You're now going to this event!"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/event_participation_approved.html.eex:58
|
||||
msgid "Go to event page"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/event_participation_approved.html.eex:70
|
||||
msgid "If you need to cancel your participation, just access the event page through link above and click on the participation button."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/event_participation_approved.text.eex:11
|
||||
msgid "If you need to cancel your participation, just access the previous link and click on the participation button."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/email.text.eex:6
|
||||
msgid "Learn more about Mobilizon:"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/report.text.eex:1
|
||||
msgid "New report from %{reporter} on %{instance}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/event_participation_approved.text.eex:1
|
||||
msgid "Participation approved"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/event_participation_rejected.text.eex:1
|
||||
msgid "Participation rejected"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/password_reset.text.eex:1
|
||||
msgid "Password reset"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/password_reset.text.eex:7
|
||||
msgid "Resetting your password is easy. Just click the link below and follow the instructions. We'll have you up and running in no time."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/event_participation_rejected.html.eex:13
|
||||
msgid "Sorry!"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/event_participation_rejected.html.eex:45
|
||||
#: lib/mobilizon_web/templates/email/event_participation_rejected.text.eex:7
|
||||
msgid "Unfortunately, the organizers rejected your participation."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.text.eex:5
|
||||
msgid "You created an account on %{host} with this email address. You are one click away from activating it. If this wasn't you, please ignore this email."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/password_reset.text.eex:5
|
||||
msgid "You requested a new password for your account on %{host}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/event_participation_approved.html.eex:38
|
||||
#: lib/mobilizon_web/templates/email/event_participation_rejected.html.eex:38
|
||||
msgid "You requested to participate in event %{title}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/event_participation_approved.text.eex:5
|
||||
#: lib/mobilizon_web/templates/email/event_participation_rejected.text.eex:5
|
||||
msgid "You requested to participate in event %{title}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/email/participation.ex:73
|
||||
msgid "Your participation to event %{title} has been approved"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/email/participation.ex:52
|
||||
msgid "Your participation to event %{title} has been rejected"
|
||||
msgstr ""
|
||||
|
93
priv/gettext/cs/LC_MESSAGES/errors.po
Normal file
93
priv/gettext/cs/LC_MESSAGES/errors.po
Normal file
@ -0,0 +1,93 @@
|
||||
## `msgid`s in this file come from POT (.pot) files.
|
||||
##
|
||||
## Do not add, change, or remove `msgid`s manually here as
|
||||
## they're tied to the ones in the corresponding POT file
|
||||
## (with the same domain).
|
||||
##
|
||||
## Use `mix gettext.extract --merge` or `mix gettext.merge`
|
||||
## to merge POT files into PO files.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: cs\n"
|
||||
"Plural-Forms: nplurals=3\n"
|
||||
|
||||
msgid "can't be blank"
|
||||
msgstr ""
|
||||
|
||||
msgid "has already been taken"
|
||||
msgstr ""
|
||||
|
||||
msgid "is invalid"
|
||||
msgstr ""
|
||||
|
||||
msgid "must be accepted"
|
||||
msgstr ""
|
||||
|
||||
msgid "has invalid format"
|
||||
msgstr ""
|
||||
|
||||
msgid "has an invalid entry"
|
||||
msgstr ""
|
||||
|
||||
msgid "is reserved"
|
||||
msgstr ""
|
||||
|
||||
msgid "does not match confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid "is still associated with this entry"
|
||||
msgstr ""
|
||||
|
||||
msgid "are still associated with this entry"
|
||||
msgstr ""
|
||||
|
||||
msgid "should be %{count} character(s)"
|
||||
msgid_plural "should be %{count} character(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
|
||||
msgid "should have %{count} item(s)"
|
||||
msgid_plural "should have %{count} item(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
|
||||
msgid "should be at least %{count} character(s)"
|
||||
msgid_plural "should be at least %{count} character(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
|
||||
msgid "should have at least %{count} item(s)"
|
||||
msgid_plural "should have at least %{count} item(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
|
||||
msgid "should be at most %{count} character(s)"
|
||||
msgid_plural "should be at most %{count} character(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
|
||||
msgid "should have at most %{count} item(s)"
|
||||
msgid_plural "should have at most %{count} item(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
|
||||
msgid "must be less than %{number}"
|
||||
msgstr ""
|
||||
|
||||
msgid "must be greater than %{number}"
|
||||
msgstr ""
|
||||
|
||||
msgid "must be less than or equal to %{number}"
|
||||
msgstr ""
|
||||
|
||||
msgid "must be greater than or equal to %{number}"
|
||||
msgstr ""
|
||||
|
||||
msgid "must be equal to %{number}"
|
||||
msgstr ""
|
@ -12,129 +12,231 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Translate Toolkit 2.4.0\n"
|
||||
|
||||
#: lib/mobilizon_web/templates/email/email.text.eex:3
|
||||
#, elixir-format
|
||||
msgid "An email sent by Mobilizon on %{instance}."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:48
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/password_reset.text.eex:12
|
||||
msgid "If you didn't request this, please ignore this email. Your password won't change until you access the link below and create a new one."
|
||||
msgstr ""
|
||||
|
||||
#: lib/service/export/feed.ex:161
|
||||
#, elixir-format
|
||||
#: lib/service/export/feed.ex:169
|
||||
msgid "Feed for %{email} on Mobilizon"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:122
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:122
|
||||
#: lib/mobilizon_web/templates/email/email.text.eex:6
|
||||
msgid "%{instance} is a Mobilizon server."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:38
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:38
|
||||
msgid "%{reporter_name} (%{reporter_username}) reported the following content."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:48
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:48
|
||||
msgid "%{title} by %{creator}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:58
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:58
|
||||
msgid "Activate my account"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:91
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:94
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:91
|
||||
msgid "Ask the community on Framacolibri"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:62
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:62
|
||||
#: lib/mobilizon_web/templates/email/report.text.eex:11
|
||||
msgid "Comments"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:46
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:46
|
||||
#: lib/mobilizon_web/templates/email/report.text.eex:6
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:45
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:45
|
||||
msgid "If you didn't request this, please ignore this email."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/email/user.ex:46
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/email/user.ex:45
|
||||
msgid "Instructions to reset your password on %{instance}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:123
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:123
|
||||
msgid "Learn more about Mobilizon."
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:13
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/registration_confirmation.html.eex:13
|
||||
msgid "Nearly here!"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:88
|
||||
#: lib/mobilizon_web/templates/email/password_reset.html.eex:91
|
||||
#, elixir-format
|
||||
#: lib/mobilizon_web/templates/email/email.html.eex:88
|
||||
msgid "Need some help? Something not working properly?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/mobilizon_web/templates/email/report.html.eex:13
|
||||
#, elixir-format
|
||||