Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
d02d62bd0d
|
@ -42,6 +42,7 @@ import { usernameWithDomain } from "@/types/actor";
|
||||||
import { formatTimeString } from "@/filters/datetime";
|
import { formatTimeString } from "@/filters/datetime";
|
||||||
import {
|
import {
|
||||||
ActivityEventCommentSubject,
|
ActivityEventCommentSubject,
|
||||||
|
ActivityEventParticipantSubject,
|
||||||
ActivityEventSubject,
|
ActivityEventSubject,
|
||||||
} from "@/types/enums";
|
} from "@/types/enums";
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
|
@ -90,6 +91,14 @@ const translation = computed((): string | undefined => {
|
||||||
return "You posted a comment on the event {event}.";
|
return "You posted a comment on the event {event}.";
|
||||||
}
|
}
|
||||||
return "{profile} posted a comment on the event {event}.";
|
return "{profile} posted a comment on the event {event}.";
|
||||||
|
case ActivityEventParticipantSubject.EVENT_NEW_PARTICIPATION:
|
||||||
|
if (isAuthorCurrentActor.value) {
|
||||||
|
return "You joined the event {event}.";
|
||||||
|
}
|
||||||
|
if (props.activity.author.preferredUsername === "anonymous") {
|
||||||
|
return "An anonymous profile joined the event {event}.";
|
||||||
|
}
|
||||||
|
return "{profile} joined the the event {event}.";
|
||||||
default:
|
default:
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ import { EventJoinOptions } from "@/types/enums";
|
||||||
import { IParticipant } from "../../types/participant.model";
|
import { IParticipant } from "../../types/participant.model";
|
||||||
import RouteName from "../../router/name";
|
import RouteName from "../../router/name";
|
||||||
import { CONFIRM_PARTICIPATION } from "../../graphql/event";
|
import { CONFIRM_PARTICIPATION } from "../../graphql/event";
|
||||||
import { computed, ref } from "vue";
|
import { computed, ref, watchEffect } from "vue";
|
||||||
import { useMutation } from "@vue/apollo-composable";
|
import { useMutation } from "@vue/apollo-composable";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useHead } from "@vueuse/head";
|
import { useHead } from "@vueuse/head";
|
||||||
|
@ -90,9 +90,15 @@ const { onDone, onError, mutate } = useMutation<{
|
||||||
confirmParticipation: IParticipant;
|
confirmParticipation: IParticipant;
|
||||||
}>(CONFIRM_PARTICIPATION);
|
}>(CONFIRM_PARTICIPATION);
|
||||||
|
|
||||||
mutate(() => ({
|
const participationToken = computed(() => props.token);
|
||||||
token: props.token,
|
|
||||||
}));
|
watchEffect(() => {
|
||||||
|
if (participationToken.value) {
|
||||||
|
mutate({
|
||||||
|
token: participationToken.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
onDone(async ({ data }) => {
|
onDone(async ({ data }) => {
|
||||||
participation.value = data?.confirmParticipation;
|
participation.value = data?.confirmParticipation;
|
||||||
|
|
|
@ -70,14 +70,16 @@ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||||
|
|
||||||
const { loggedUser } = useUserSettings();
|
const { loggedUser } = useUserSettings();
|
||||||
|
|
||||||
|
const { mutate: doUpdateLocale } = updateLocale();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
updateLocale(locale as unknown as string);
|
doUpdateLocale({ locale: locale as unknown as string });
|
||||||
doUpdateSetting({ timezone });
|
doUpdateSetting({ timezone });
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(locale, () => {
|
watch(locale, () => {
|
||||||
if (locale.value) {
|
if (locale.value) {
|
||||||
updateLocale(locale.value as string);
|
doUpdateLocale({ locale: locale as unknown as string });
|
||||||
saveLocaleData(locale.value as string);
|
saveLocaleData(locale.value as string);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -59,12 +59,8 @@ export async function doUpdateSetting(
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateLocale(locale: string) {
|
export function updateLocale() {
|
||||||
useMutation<{ id: string; locale: string }>(UPDATE_USER_LOCALE, () => ({
|
return useMutation<{ id: string; locale: string }>(UPDATE_USER_LOCALE);
|
||||||
variables: {
|
|
||||||
locale,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function registerAccount() {
|
export function registerAccount() {
|
||||||
|
|
|
@ -1579,5 +1579,8 @@
|
||||||
"Access drafts events": "Access drafts events",
|
"Access drafts events": "Access drafts events",
|
||||||
"This application will be allowed to list and view your draft events": "This application will be allowed to list and view your draft events",
|
"This application will be allowed to list and view your draft events": "This application will be allowed to list and view your draft events",
|
||||||
"Access group suggested events": "Access group suggested events",
|
"Access group suggested events": "Access group suggested events",
|
||||||
"This application will be allowed to list your suggested group events": "This application will be allowed to list your suggested group events"
|
"This application will be allowed to list your suggested group events": "This application will be allowed to list your suggested group events",
|
||||||
|
"{profile} joined the the event {event}.": "{profile} joined the the event {event}.",
|
||||||
|
"You joined the event {event}.": "You joined the event {event}.",
|
||||||
|
"An anonymous profile joined the event {event}.": "An anonymous profile joined the event {event}."
|
||||||
}
|
}
|
|
@ -151,7 +151,7 @@
|
||||||
"Attending": "Participant⋅e",
|
"Attending": "Participant⋅e",
|
||||||
"Authorize": "Autoriser",
|
"Authorize": "Autoriser",
|
||||||
"Authorize application": "Autoriser l'application",
|
"Authorize application": "Autoriser l'application",
|
||||||
"Authorized on {authorization_date}": "Authorisée le {authorization_date}",
|
"Authorized on {authorization_date}": "Autorisée le {authorization_date}",
|
||||||
"Autorize this application to access your account?": "Autoriser cette application à accéder à votre compte ?",
|
"Autorize this application to access your account?": "Autoriser cette application à accéder à votre compte ?",
|
||||||
"Avatar": "Avatar",
|
"Avatar": "Avatar",
|
||||||
"Back to group list": "Retour à la liste des groupes",
|
"Back to group list": "Retour à la liste des groupes",
|
||||||
|
@ -1575,5 +1575,8 @@
|
||||||
"Access drafts events": "Accéder aux événements brouillons",
|
"Access drafts events": "Accéder aux événements brouillons",
|
||||||
"This application will be allowed to list and view your draft events": "Cetta application sera autorisée à lister et accéder à vos événements brouillons",
|
"This application will be allowed to list and view your draft events": "Cetta application sera autorisée à lister et accéder à vos événements brouillons",
|
||||||
"Access group suggested events": "Accéder aux événements des groupes suggérés",
|
"Access group suggested events": "Accéder aux événements des groupes suggérés",
|
||||||
"This application will be allowed to list your suggested group events": "Cetta application sera autorisée à lister les événements de vos groupes qui vous sont suggérés"
|
"This application will be allowed to list your suggested group events": "Cetta application sera autorisée à lister les événements de vos groupes qui vous sont suggérés",
|
||||||
|
"{profile} joined the the event {event}.": "{profile} a rejoint l'événement {event}.",
|
||||||
|
"You joined the event {event}.": "Vous avez rejoint l'événement {event}.",
|
||||||
|
"An anonymous profile joined the event {event}.": "Un profil anonyme a rejoint l'événement {event}."
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,7 @@
|
||||||
"Allow all comments from users with accounts": "Pozwalaj na wszystkie komentarze od zalogowanych użytkowników lub użytkowniczek",
|
"Allow all comments from users with accounts": "Pozwalaj na wszystkie komentarze od zalogowanych użytkowników lub użytkowniczek",
|
||||||
"Allow registrations": "Pozwól na rejestrację",
|
"Allow registrations": "Pozwól na rejestrację",
|
||||||
"An URL to an external ticketing platform": "Adres URL do zewnętrznej platformy sprzedaży biletów",
|
"An URL to an external ticketing platform": "Adres URL do zewnętrznej platformy sprzedaży biletów",
|
||||||
|
"An anonymous profile joined the event {event}.": "Anonimowy profil przystąpił do wydarzenia {event}.",
|
||||||
"An error has occured while refreshing the page.": "Wystąpił błąd podczas odświeżania strony.",
|
"An error has occured while refreshing the page.": "Wystąpił błąd podczas odświeżania strony.",
|
||||||
"An error has occured. Sorry about that. You may try to reload the page.": "Przepraszamy, ale wystąpił błąd. Możesz spróbować odświeżyć stronę.",
|
"An error has occured. Sorry about that. You may try to reload the page.": "Przepraszamy, ale wystąpił błąd. Możesz spróbować odświeżyć stronę.",
|
||||||
"An ethical alternative": "Etyczna alternatywa",
|
"An ethical alternative": "Etyczna alternatywa",
|
||||||
|
@ -696,7 +697,7 @@
|
||||||
"No group found": "Nie znaleziono grupy",
|
"No group found": "Nie znaleziono grupy",
|
||||||
"No group matches the filters": "Żadna grupa nie spełnia kryteriów filtra",
|
"No group matches the filters": "Żadna grupa nie spełnia kryteriów filtra",
|
||||||
"No group member found": "Nie znaleziono żadnego członka ani członkini grupy",
|
"No group member found": "Nie znaleziono żadnego członka ani członkini grupy",
|
||||||
"No groups found": "Nie znaleziono grup",
|
"No groups found": "Nie znaleziono grup",
|
||||||
"No groups found for {search}": "Nie znaleziono grup dla {search}",
|
"No groups found for {search}": "Nie znaleziono grup dla {search}",
|
||||||
"No information": "nie podano",
|
"No information": "nie podano",
|
||||||
"No instance follows your instance yet.": "Żadna instancja nie obserwuje jeszcze Twojej instancji.",
|
"No instance follows your instance yet.": "Żadna instancja nie obserwuje jeszcze Twojej instancji.",
|
||||||
|
@ -1183,7 +1184,7 @@
|
||||||
"This user was not found": "Ten użytkownik / użytkowniczka nie została znaleziona",
|
"This user was not found": "Ten użytkownik / użytkowniczka nie została znaleziona",
|
||||||
"This website isn't moderated and the data that you enter will be automatically destroyed every day at 00:01 (Paris timezone).": "Ta strona nie jest moderowana i wszelkie dane które wprowadzasz będą automatycznie usuwane każdego dnia o 00:001 (strefa czasowa Paryża).",
|
"This website isn't moderated and the data that you enter will be automatically destroyed every day at 00:01 (Paris timezone).": "Ta strona nie jest moderowana i wszelkie dane które wprowadzasz będą automatycznie usuwane każdego dnia o 00:001 (strefa czasowa Paryża).",
|
||||||
"This week": "W tym tygodniu",
|
"This week": "W tym tygodniu",
|
||||||
"This weekend": "Ten weekend",
|
"This weekend": "W najbliższy weekend",
|
||||||
"This will delete / anonymize all content (events, comments, messages, participations…) created from this identity.": "Ta opcja usunie/zanonimizuje całą zawartość (wydarzenia, komentarze, wiadomości, deklaracje udziału…) utworzone z tej tożsamości.",
|
"This will delete / anonymize all content (events, comments, messages, participations…) created from this identity.": "Ta opcja usunie/zanonimizuje całą zawartość (wydarzenia, komentarze, wiadomości, deklaracje udziału…) utworzone z tej tożsamości.",
|
||||||
"Time in your timezone ({timezone})": "Czas w Twojej strefie czasowej ({timezone})",
|
"Time in your timezone ({timezone})": "Czas w Twojej strefie czasowej ({timezone})",
|
||||||
"Times in your timezone ({timezone})": "Czasy w Twojej strefie czasowej ({timezone})",
|
"Times in your timezone ({timezone})": "Czasy w Twojej strefie czasowej ({timezone})",
|
||||||
|
@ -1372,6 +1373,7 @@
|
||||||
"You have one event tomorrow.": "Nie masz jutro żadnych wydarzeń | Masz jutro jedno wydarzenie. | Masz jutro {count} wydarzeń",
|
"You have one event tomorrow.": "Nie masz jutro żadnych wydarzeń | Masz jutro jedno wydarzenie. | Masz jutro {count} wydarzeń",
|
||||||
"You haven't interacted with other instances yet.": "Nie wchodziłeś(-aś) jeszcze w interakcje z innymi instancjami.",
|
"You haven't interacted with other instances yet.": "Nie wchodziłeś(-aś) jeszcze w interakcje z innymi instancjami.",
|
||||||
"You invited {member}.": "Zaprosiłeś(-aś) {member}.",
|
"You invited {member}.": "Zaprosiłeś(-aś) {member}.",
|
||||||
|
"You joined the event {event}.": "Ty przystąpiłeś(-aś) do wydarzenia {event}.",
|
||||||
"You may also:": "Możesz także:",
|
"You may also:": "Możesz także:",
|
||||||
"You may clear all participation information for this device with the buttons below.": "Wszystkie informacje o uczestnictwie zapisane na tym urządzeniu można usunąć przyciskami poniżej.",
|
"You may clear all participation information for this device with the buttons below.": "Wszystkie informacje o uczestnictwie zapisane na tym urządzeniu można usunąć przyciskami poniżej.",
|
||||||
"You may now close this page or {return_to_the_homepage}.": "Teraz możesz zamknąć tę stronę lub {return_to_the_homepage}.",
|
"You may now close this page or {return_to_the_homepage}.": "Teraz możesz zamknąć tę stronę lub {return_to_the_homepage}.",
|
||||||
|
@ -1556,6 +1558,7 @@
|
||||||
"{profile} demoted {member} to moderator.": "{profile} zdegradował(a)(o) {member} do roli moderatora(-ki).",
|
"{profile} demoted {member} to moderator.": "{profile} zdegradował(a)(o) {member} do roli moderatora(-ki).",
|
||||||
"{profile} demoted {member} to simple member.": "{profile} zdegradował(a)(o) {member} do roli zwykłego członka / zwykłej członkini.",
|
"{profile} demoted {member} to simple member.": "{profile} zdegradował(a)(o) {member} do roli zwykłego członka / zwykłej członkini.",
|
||||||
"{profile} excluded member {member}.": "{profile} wykluczył(a)(o) członka / członkinię {member}.",
|
"{profile} excluded member {member}.": "{profile} wykluczył(a)(o) członka / członkinię {member}.",
|
||||||
|
"{profile} joined the the event {event}.": "Profil {profile} przystąpił do wydarzenia {event}.",
|
||||||
"{profile} moved the folder {resource} into {new_path}.": "Katalog {resource} został przeniesiony do {new_path} przez {profile}.",
|
"{profile} moved the folder {resource} into {new_path}.": "Katalog {resource} został przeniesiony do {new_path} przez {profile}.",
|
||||||
"{profile} moved the folder {resource} to the root folder.": "Katalog {resource} został przeniesiony do katalogu głównego przez {profile}.",
|
"{profile} moved the folder {resource} to the root folder.": "Katalog {resource} został przeniesiony do katalogu głównego przez {profile}.",
|
||||||
"{profile} moved the resource {resource} into {new_path}.": "Zasób {resource} został przeniesiony do {new_path} przez {profile}.",
|
"{profile} moved the resource {resource} into {new_path}.": "Zasób {resource} został przeniesiony do {new_path} przez {profile}.",
|
||||||
|
|
|
@ -32,9 +32,8 @@ export async function subscribeUserToPush(): Promise<PushSubscription | null> {
|
||||||
};
|
};
|
||||||
const registration = await navigator.serviceWorker.ready;
|
const registration = await navigator.serviceWorker.ready;
|
||||||
try {
|
try {
|
||||||
const pushSubscription = await registration.pushManager.subscribe(
|
const pushSubscription =
|
||||||
subscribeOptions
|
await registration.pushManager.subscribe(subscribeOptions);
|
||||||
);
|
|
||||||
console.debug("Received PushSubscription: ", pushSubscription);
|
console.debug("Received PushSubscription: ", pushSubscription);
|
||||||
resolve(pushSubscription);
|
resolve(pushSubscription);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { IMember } from "./actor/member.model";
|
||||||
import {
|
import {
|
||||||
ActivityDiscussionSubject,
|
ActivityDiscussionSubject,
|
||||||
ActivityEventCommentSubject,
|
ActivityEventCommentSubject,
|
||||||
|
ActivityEventParticipantSubject,
|
||||||
ActivityEventSubject,
|
ActivityEventSubject,
|
||||||
ActivityGroupSubject,
|
ActivityGroupSubject,
|
||||||
ActivityMemberSubject,
|
ActivityMemberSubject,
|
||||||
|
@ -21,7 +22,8 @@ export type ActivitySubject =
|
||||||
| ActivityResourceSubject
|
| ActivityResourceSubject
|
||||||
| ActivityDiscussionSubject
|
| ActivityDiscussionSubject
|
||||||
| ActivityGroupSubject
|
| ActivityGroupSubject
|
||||||
| ActivityEventCommentSubject;
|
| ActivityEventCommentSubject
|
||||||
|
| ActivityEventParticipantSubject;
|
||||||
|
|
||||||
export interface IActivity {
|
export interface IActivity {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
@ -200,6 +200,10 @@ export enum ActivityEventCommentSubject {
|
||||||
COMMENT_POSTED = "comment_posted",
|
COMMENT_POSTED = "comment_posted",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ActivityEventParticipantSubject {
|
||||||
|
EVENT_NEW_PARTICIPATION = "event_new_participation",
|
||||||
|
}
|
||||||
|
|
||||||
export enum ActivityPostSubject {
|
export enum ActivityPostSubject {
|
||||||
POST_CREATED = "post_created",
|
POST_CREATED = "post_created",
|
||||||
POST_UPDATED = "post_updated",
|
POST_UPDATED = "post_updated",
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<div class="">
|
<div class="">
|
||||||
<o-field :label="t('Status')" horizontal label-for="role-select">
|
<o-field :label="t('Status')" horizontal label-for="role-select">
|
||||||
<o-select v-model="role" id="role-select">
|
<o-select v-model="role" id="role-select">
|
||||||
<option :value="null">
|
<option value="EVERYTHING">
|
||||||
{{ t("Everything") }}
|
{{ t("Everything") }}
|
||||||
</option>
|
</option>
|
||||||
<option :value="ParticipantRole.CREATOR">
|
<option :value="ParticipantRole.CREATOR">
|
||||||
|
@ -303,17 +303,15 @@ const participantsExportFormats = useParticipantsExportFormats();
|
||||||
const ellipsize = (text?: string) =>
|
const ellipsize = (text?: string) =>
|
||||||
text && text.substring(0, MESSAGE_ELLIPSIS_LENGTH).concat("…");
|
text && text.substring(0, MESSAGE_ELLIPSIS_LENGTH).concat("…");
|
||||||
|
|
||||||
// metaInfo() {
|
const eventId = computed(() => props.eventId);
|
||||||
// return {
|
|
||||||
// title: this.t("Participants") as string,
|
const ParticipantAllRoles = { ...ParticipantRole, EVERYTHING: "EVERYTHING" };
|
||||||
// };
|
|
||||||
// },
|
|
||||||
|
|
||||||
const page = useRouteQuery("page", 1, integerTransformer);
|
const page = useRouteQuery("page", 1, integerTransformer);
|
||||||
const role = useRouteQuery(
|
const role = useRouteQuery(
|
||||||
"role",
|
"role",
|
||||||
ParticipantRole.PARTICIPANT,
|
"EVERYTHING",
|
||||||
enumTransformer(ParticipantRole)
|
enumTransformer(ParticipantAllRoles)
|
||||||
);
|
);
|
||||||
|
|
||||||
const checkedRows = ref<IParticipant[]>([]);
|
const checkedRows = ref<IParticipant[]>([]);
|
||||||
|
@ -325,10 +323,10 @@ const { result: participantsResult, loading: participantsLoading } = useQuery<{
|
||||||
}>(
|
}>(
|
||||||
PARTICIPANTS,
|
PARTICIPANTS,
|
||||||
() => ({
|
() => ({
|
||||||
uuid: props.eventId,
|
uuid: eventId.value,
|
||||||
page: page.value,
|
page: page.value,
|
||||||
limit: PARTICIPANTS_PER_PAGE,
|
limit: PARTICIPANTS_PER_PAGE,
|
||||||
roles: role.value,
|
roles: role.value === "EVERYTHING" ? undefined : role.value,
|
||||||
}),
|
}),
|
||||||
() => ({
|
() => ({
|
||||||
enabled:
|
enabled:
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
<o-select
|
<o-select
|
||||||
:loading="loadingTimezones || loadingUserSettings"
|
:loading="loadingTimezones || loadingUserSettings"
|
||||||
v-model="$i18n.locale"
|
v-model="$i18n.locale"
|
||||||
|
@update:modelValue="updateLanguage"
|
||||||
:placeholder="t('Select a language')"
|
:placeholder="t('Select a language')"
|
||||||
id="setting-language"
|
id="setting-language"
|
||||||
>
|
>
|
||||||
|
@ -147,7 +148,7 @@ import RouteName from "../../router/name";
|
||||||
import { AddressSearchType } from "@/types/enums";
|
import { AddressSearchType } from "@/types/enums";
|
||||||
import { Address, IAddress } from "@/types/address.model";
|
import { Address, IAddress } from "@/types/address.model";
|
||||||
import { useTimezones } from "@/composition/apollo/config";
|
import { useTimezones } from "@/composition/apollo/config";
|
||||||
import { useUserSettings } from "@/composition/apollo/user";
|
import { useUserSettings, updateLocale } from "@/composition/apollo/user";
|
||||||
import { useHead } from "@vueuse/head";
|
import { useHead } from "@vueuse/head";
|
||||||
import { computed, defineAsyncComponent, ref, watch } from "vue";
|
import { computed, defineAsyncComponent, ref, watch } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
@ -172,6 +173,12 @@ useHead({
|
||||||
const theme = ref(localStorage.getItem("theme"));
|
const theme = ref(localStorage.getItem("theme"));
|
||||||
const systemTheme = ref(!("theme" in localStorage));
|
const systemTheme = ref(!("theme" in localStorage));
|
||||||
|
|
||||||
|
const { mutate: doUpdateLocale } = updateLocale();
|
||||||
|
|
||||||
|
const updateLanguage = (newLocale: string) => {
|
||||||
|
doUpdateLocale({ locale: newLocale });
|
||||||
|
};
|
||||||
|
|
||||||
watch(systemTheme, (newSystemTheme) => {
|
watch(systemTheme, (newSystemTheme) => {
|
||||||
console.debug("changing system theme", newSystemTheme);
|
console.debug("changing system theme", newSystemTheme);
|
||||||
if (newSystemTheme) {
|
if (newSystemTheme) {
|
||||||
|
|
|
@ -82,6 +82,11 @@ defmodule Mobilizon.Federation.ActivityPub.Actions.Accept do
|
||||||
)
|
)
|
||||||
|
|
||||||
Scheduler.trigger_notifications_for_participant(participant)
|
Scheduler.trigger_notifications_for_participant(participant)
|
||||||
|
|
||||||
|
Mobilizon.Service.Activity.Participant.insert_activity(participant,
|
||||||
|
subject: "event_new_participation"
|
||||||
|
)
|
||||||
|
|
||||||
participant_as_data = Convertible.model_to_as(participant)
|
participant_as_data = Convertible.model_to_as(participant)
|
||||||
audience = Audience.get_audience(participant)
|
audience = Audience.get_audience(participant)
|
||||||
|
|
||||||
|
|
|
@ -224,6 +224,10 @@ defmodule Mobilizon.Federation.ActivityPub.Types.Events do
|
||||||
cond do
|
cond do
|
||||||
Mobilizon.Events.get_default_participant_role(event) == :participant &&
|
Mobilizon.Events.get_default_participant_role(event) == :participant &&
|
||||||
role == :participant ->
|
role == :participant ->
|
||||||
|
Mobilizon.Service.Activity.Participant.insert_activity(participant,
|
||||||
|
subject: "event_new_participation"
|
||||||
|
)
|
||||||
|
|
||||||
{:accept,
|
{:accept,
|
||||||
Actions.Accept.accept(
|
Actions.Accept.accept(
|
||||||
:join,
|
:join,
|
||||||
|
|
|
@ -6,6 +6,7 @@ defmodule Mobilizon.GraphQL.Resolvers.PushSubscription do
|
||||||
alias Mobilizon.Storage.Page
|
alias Mobilizon.Storage.Page
|
||||||
alias Mobilizon.Users
|
alias Mobilizon.Users
|
||||||
alias Mobilizon.Users.{PushSubscription, User}
|
alias Mobilizon.Users.{PushSubscription, User}
|
||||||
|
import Mobilizon.Web.Gettext
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
List all of an user's registered push subscriptions
|
List all of an user's registered push subscriptions
|
||||||
|
@ -33,6 +34,19 @@ defmodule Mobilizon.GraphQL.Resolvers.PushSubscription do
|
||||||
{:ok, %PushSubscription{}} ->
|
{:ok, %PushSubscription{}} ->
|
||||||
{:ok, "OK"}
|
{:ok, "OK"}
|
||||||
|
|
||||||
|
{:error,
|
||||||
|
%Ecto.Changeset{
|
||||||
|
errors: [
|
||||||
|
digest:
|
||||||
|
{"has already been taken",
|
||||||
|
[
|
||||||
|
constraint: :unique,
|
||||||
|
constraint_name: "user_push_subscriptions_user_id_digest_index"
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}} ->
|
||||||
|
{:error, dgettext("errors", "The same push subscription has already been registered")}
|
||||||
|
|
||||||
{:error, err} ->
|
{:error, err} ->
|
||||||
require Logger
|
require Logger
|
||||||
Logger.error(inspect(err))
|
Logger.error(inspect(err))
|
||||||
|
|
|
@ -4,6 +4,7 @@ defmodule Mobilizon.GraphQL.Schema.Users.PushSubscription do
|
||||||
"""
|
"""
|
||||||
use Absinthe.Schema.Notation
|
use Absinthe.Schema.Notation
|
||||||
alias Mobilizon.GraphQL.Resolvers.PushSubscription
|
alias Mobilizon.GraphQL.Resolvers.PushSubscription
|
||||||
|
alias Mobilizon.Users.User
|
||||||
|
|
||||||
# object :push_subscription do
|
# object :push_subscription do
|
||||||
# field(:id, :id)
|
# field(:id, :id)
|
||||||
|
@ -29,8 +30,9 @@ defmodule Mobilizon.GraphQL.Schema.Users.PushSubscription do
|
||||||
|
|
||||||
middleware(Rajska.QueryAuthorization,
|
middleware(Rajska.QueryAuthorization,
|
||||||
permit: :user,
|
permit: :user,
|
||||||
scope: false,
|
scope: User,
|
||||||
rule: :"write:user:setting:push"
|
rule: :"write:user:setting:push",
|
||||||
|
args: %{}
|
||||||
)
|
)
|
||||||
|
|
||||||
resolve(&PushSubscription.register_push_subscription/3)
|
resolve(&PushSubscription.register_push_subscription/3)
|
||||||
|
@ -41,8 +43,9 @@ defmodule Mobilizon.GraphQL.Schema.Users.PushSubscription do
|
||||||
|
|
||||||
middleware(Rajska.QueryAuthorization,
|
middleware(Rajska.QueryAuthorization,
|
||||||
permit: :user,
|
permit: :user,
|
||||||
scope: false,
|
scope: User,
|
||||||
rule: :"write:user:setting:push"
|
rule: :"write:user:setting:push",
|
||||||
|
args: %{}
|
||||||
)
|
)
|
||||||
|
|
||||||
resolve(&PushSubscription.unregister_push_subscription/3)
|
resolve(&PushSubscription.unregister_push_subscription/3)
|
||||||
|
|
|
@ -19,6 +19,7 @@ defmodule Mobilizon.Activities do
|
||||||
|
|
||||||
@activity_types ["event", "post", "discussion", "resource", "group", "member", "comment"]
|
@activity_types ["event", "post", "discussion", "resource", "group", "member", "comment"]
|
||||||
@event_activity_subjects ["event_created", "event_updated", "event_deleted", "comment_posted"]
|
@event_activity_subjects ["event_created", "event_updated", "event_deleted", "comment_posted"]
|
||||||
|
@participant_activity_subjects ["event_new_participation"]
|
||||||
@post_activity_subjects ["post_created", "post_updated", "post_deleted"]
|
@post_activity_subjects ["post_created", "post_updated", "post_deleted"]
|
||||||
@discussion_activity_subjects [
|
@discussion_activity_subjects [
|
||||||
"discussion_created",
|
"discussion_created",
|
||||||
|
@ -48,12 +49,23 @@ defmodule Mobilizon.Activities do
|
||||||
@settings_activity_subjects ["group_created", "group_updated"]
|
@settings_activity_subjects ["group_created", "group_updated"]
|
||||||
|
|
||||||
@subjects @event_activity_subjects ++
|
@subjects @event_activity_subjects ++
|
||||||
|
@participant_activity_subjects ++
|
||||||
@post_activity_subjects ++
|
@post_activity_subjects ++
|
||||||
@discussion_activity_subjects ++
|
@discussion_activity_subjects ++
|
||||||
@resource_activity_subjects ++
|
@resource_activity_subjects ++
|
||||||
@member_activity_subjects ++ @settings_activity_subjects
|
@member_activity_subjects ++ @settings_activity_subjects
|
||||||
|
|
||||||
@object_type ["event", "actor", "post", "discussion", "resource", "member", "group", "comment"]
|
@object_type [
|
||||||
|
"event",
|
||||||
|
"participant",
|
||||||
|
"actor",
|
||||||
|
"post",
|
||||||
|
"discussion",
|
||||||
|
"resource",
|
||||||
|
"member",
|
||||||
|
"group",
|
||||||
|
"comment"
|
||||||
|
]
|
||||||
|
|
||||||
defenum(Type, @activity_types)
|
defenum(Type, @activity_types)
|
||||||
defenum(Subject, @subjects)
|
defenum(Subject, @subjects)
|
||||||
|
|
|
@ -4,7 +4,17 @@ defmodule Mobilizon.Service.Activity do
|
||||||
"""
|
"""
|
||||||
|
|
||||||
alias Mobilizon.Activities.Activity
|
alias Mobilizon.Activities.Activity
|
||||||
alias Mobilizon.Service.Activity.{Comment, Discussion, Event, Group, Member, Post, Resource}
|
|
||||||
|
alias Mobilizon.Service.Activity.{
|
||||||
|
Comment,
|
||||||
|
Discussion,
|
||||||
|
Event,
|
||||||
|
Group,
|
||||||
|
Member,
|
||||||
|
Participant,
|
||||||
|
Post,
|
||||||
|
Resource
|
||||||
|
}
|
||||||
|
|
||||||
@callback insert_activity(entity :: struct(), options :: Keyword.t()) ::
|
@callback insert_activity(entity :: struct(), options :: Keyword.t()) ::
|
||||||
{:ok, Oban.Job.t()} | {:ok, any()} | {:error, Ecto.Changeset.t()}
|
{:ok, Oban.Job.t()} | {:ok, any()} | {:error, Ecto.Changeset.t()}
|
||||||
|
@ -45,4 +55,8 @@ defmodule Mobilizon.Service.Activity do
|
||||||
defp do_get_object(:comment, comment_id) do
|
defp do_get_object(:comment, comment_id) do
|
||||||
Comment.get_object(comment_id)
|
Comment.get_object(comment_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp do_get_object(:participant, participant_id) do
|
||||||
|
Participant.get_object(participant_id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
48
lib/service/activity/participant.ex
Normal file
48
lib/service/activity/participant.ex
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
defmodule Mobilizon.Service.Activity.Participant do
|
||||||
|
@moduledoc """
|
||||||
|
Insert an event activity
|
||||||
|
"""
|
||||||
|
alias Mobilizon.{Actors, Events}
|
||||||
|
alias Mobilizon.Actors.Actor
|
||||||
|
alias Mobilizon.Events.Participant
|
||||||
|
alias Mobilizon.Service.Activity
|
||||||
|
alias Mobilizon.Service.Workers.ActivityBuilder
|
||||||
|
|
||||||
|
@behaviour Activity
|
||||||
|
|
||||||
|
@impl Activity
|
||||||
|
def insert_activity(event, options \\ [])
|
||||||
|
|
||||||
|
def insert_activity(
|
||||||
|
%Participant{event_id: event_id, actor_id: actor_id, id: participant_id} =
|
||||||
|
_participant,
|
||||||
|
options
|
||||||
|
) do
|
||||||
|
actor = Actors.get_actor(actor_id)
|
||||||
|
event = Events.get_event!(event_id)
|
||||||
|
subject = Keyword.fetch!(options, :subject)
|
||||||
|
|
||||||
|
ActivityBuilder.enqueue(:build_activity, %{
|
||||||
|
"type" => "event",
|
||||||
|
"subject" => subject,
|
||||||
|
"subject_params" => %{
|
||||||
|
actor_name: Actor.display_name(actor),
|
||||||
|
event_title: event.title,
|
||||||
|
event_uuid: event.uuid
|
||||||
|
},
|
||||||
|
"group_id" => event.attributed_to_id,
|
||||||
|
"author_id" => actor.id,
|
||||||
|
"object_type" => "participant",
|
||||||
|
"object_id" => participant_id,
|
||||||
|
"inserted_at" => DateTime.utc_now()
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Activity
|
||||||
|
def insert_activity(_, _), do: {:ok, nil}
|
||||||
|
|
||||||
|
@impl Activity
|
||||||
|
def get_object(participant_id) do
|
||||||
|
Events.get_participant(participant_id)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,6 @@
|
||||||
defmodule Mobilizon.Service.Activity.Renderer.Event do
|
defmodule Mobilizon.Service.Activity.Renderer.Event do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Insert a comment activity
|
Insert an event activity
|
||||||
"""
|
"""
|
||||||
alias Mobilizon.Activities.Activity
|
alias Mobilizon.Activities.Activity
|
||||||
alias Mobilizon.Actors.Actor
|
alias Mobilizon.Actors.Actor
|
||||||
|
@ -67,6 +67,16 @@ defmodule Mobilizon.Service.Activity.Renderer.Event do
|
||||||
url: event_url(activity)
|
url: event_url(activity)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
:event_new_participation ->
|
||||||
|
%{
|
||||||
|
body:
|
||||||
|
dgettext("activity", "%{profile} joined your event %{event}.", %{
|
||||||
|
profile: profile(activity),
|
||||||
|
event: title(activity)
|
||||||
|
}),
|
||||||
|
url: event_url(activity)
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ defmodule Mobilizon.Service.DateTime do
|
||||||
Module to represent a datetime in a given locale
|
Module to represent a datetime in a given locale
|
||||||
"""
|
"""
|
||||||
alias Cldr.DateTime.Relative
|
alias Cldr.DateTime.Relative
|
||||||
|
alias Mobilizon.Cldr, as: MobilizonCldr
|
||||||
|
import Mobilizon.Cldr, only: [locale_or_default: 1]
|
||||||
|
|
||||||
@typep to_string_format :: :short | :medium | :long | :full
|
@typep to_string_format :: :short | :medium | :long | :full
|
||||||
|
|
||||||
|
@ -10,25 +12,25 @@ defmodule Mobilizon.Service.DateTime do
|
||||||
|
|
||||||
@spec datetime_to_string(DateTime.t(), String.t(), to_string_format()) :: String.t()
|
@spec datetime_to_string(DateTime.t(), String.t(), to_string_format()) :: String.t()
|
||||||
def datetime_to_string(%DateTime{} = datetime, locale \\ "en", format \\ :medium) do
|
def datetime_to_string(%DateTime{} = datetime, locale \\ "en", format \\ :medium) do
|
||||||
Mobilizon.Cldr.DateTime.to_string!(datetime,
|
MobilizonCldr.DateTime.to_string!(datetime,
|
||||||
format: format,
|
format: format,
|
||||||
locale: Mobilizon.Cldr.locale_or_default(locale)
|
locale: locale_or_default(locale)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec datetime_to_time_string(DateTime.t(), String.t(), to_string_format()) :: String.t()
|
@spec datetime_to_time_string(DateTime.t(), String.t(), to_string_format()) :: String.t()
|
||||||
def datetime_to_time_string(%DateTime{} = datetime, locale \\ "en", format \\ :short) do
|
def datetime_to_time_string(%DateTime{} = datetime, locale \\ "en", format \\ :short) do
|
||||||
Mobilizon.Cldr.Time.to_string!(datetime,
|
MobilizonCldr.Time.to_string!(datetime,
|
||||||
format: format,
|
format: format,
|
||||||
locale: Mobilizon.Cldr.locale_or_default(locale)
|
locale: locale_or_default(locale)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec datetime_to_date_string(DateTime.t(), String.t(), to_string_format()) :: String.t()
|
@spec datetime_to_date_string(DateTime.t(), String.t(), to_string_format()) :: String.t()
|
||||||
def datetime_to_date_string(%DateTime{} = datetime, locale \\ "en", format \\ :short) do
|
def datetime_to_date_string(%DateTime{} = datetime, locale \\ "en", format \\ :short) do
|
||||||
Mobilizon.Cldr.Date.to_string!(datetime,
|
MobilizonCldr.Date.to_string!(datetime,
|
||||||
format: format,
|
format: format,
|
||||||
locale: Mobilizon.Cldr.locale_or_default(locale)
|
locale: locale_or_default(locale)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -47,9 +49,9 @@ defmodule Mobilizon.Service.DateTime do
|
||||||
|
|
||||||
@spec datetime_relative(DateTime.t(), String.t()) :: String.t()
|
@spec datetime_relative(DateTime.t(), String.t()) :: String.t()
|
||||||
def datetime_relative(%DateTime{} = datetime, locale \\ "en") do
|
def datetime_relative(%DateTime{} = datetime, locale \\ "en") do
|
||||||
Relative.to_string!(datetime, Mobilizon.Cldr,
|
Relative.to_string!(datetime, MobilizonCldr,
|
||||||
relative_to: DateTime.utc_now(),
|
relative_to: DateTime.utc_now(),
|
||||||
locale: Mobilizon.Cldr.locale_or_default(locale)
|
locale: locale_or_default(locale)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ defmodule Mobilizon.Service.Export.Participants.Common do
|
||||||
alias Mobilizon.Events.Participant.Metadata
|
alias Mobilizon.Events.Participant.Metadata
|
||||||
alias Mobilizon.Storage.Repo
|
alias Mobilizon.Storage.Repo
|
||||||
import Mobilizon.Web.Gettext, only: [gettext: 1]
|
import Mobilizon.Web.Gettext, only: [gettext: 1]
|
||||||
|
import Mobilizon.Service.DateTime, only: [datetime_to_string: 2]
|
||||||
|
|
||||||
@spec save_upload(String.t(), String.t(), String.t(), String.t(), String.t()) ::
|
@spec save_upload(String.t(), String.t(), String.t(), String.t(), String.t()) ::
|
||||||
{:ok, Export.t()} | {:error, atom() | Ecto.Changeset.t()}
|
{:ok, Export.t()} | {:error, atom() | Ecto.Changeset.t()}
|
||||||
|
@ -58,7 +59,12 @@ defmodule Mobilizon.Service.Export.Participants.Common do
|
||||||
|
|
||||||
@spec columns :: list(String.t())
|
@spec columns :: list(String.t())
|
||||||
def columns do
|
def columns do
|
||||||
[gettext("Participant name"), gettext("Participant status"), gettext("Participant message")]
|
[
|
||||||
|
gettext("Participant name"),
|
||||||
|
gettext("Participant status"),
|
||||||
|
gettext("Participant registration date"),
|
||||||
|
gettext("Participant message")
|
||||||
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
# One hour
|
# One hour
|
||||||
|
@ -82,14 +88,26 @@ defmodule Mobilizon.Service.Export.Participants.Common do
|
||||||
|
|
||||||
@spec to_list({Participant.t(), Actor.t()}) :: list(String.t())
|
@spec to_list({Participant.t(), Actor.t()}) :: list(String.t())
|
||||||
def to_list(
|
def to_list(
|
||||||
{%Participant{role: role, metadata: metadata},
|
{%Participant{role: role, metadata: metadata, inserted_at: inserted_at},
|
||||||
%Actor{domain: nil, preferred_username: "anonymous"}}
|
%Actor{domain: nil, preferred_username: "anonymous"}}
|
||||||
) do
|
) do
|
||||||
[gettext("Anonymous participant"), translate_role(role), convert_metadata(metadata)]
|
[
|
||||||
|
gettext("Anonymous participant"),
|
||||||
|
translate_role(role),
|
||||||
|
datetime_to_string(inserted_at, Gettext.get_locale()),
|
||||||
|
convert_metadata(metadata)
|
||||||
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_list({%Participant{role: role, metadata: metadata}, %Actor{} = actor}) do
|
def to_list(
|
||||||
[Actor.display_name_and_username(actor), translate_role(role), convert_metadata(metadata)]
|
{%Participant{role: role, metadata: metadata, inserted_at: inserted_at}, %Actor{} = actor}
|
||||||
|
) do
|
||||||
|
[
|
||||||
|
Actor.display_name_and_username(actor),
|
||||||
|
translate_role(role),
|
||||||
|
datetime_to_string(inserted_at, Gettext.get_locale()),
|
||||||
|
convert_metadata(metadata)
|
||||||
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec convert_metadata(Metadata.t() | nil) :: String.t()
|
@spec convert_metadata(Metadata.t() | nil) :: String.t()
|
||||||
|
|
|
@ -96,7 +96,7 @@ defmodule Mobilizon.Service.Notifier.Email do
|
||||||
|
|
||||||
defp can_send_activity?(activity, user, options) do
|
defp can_send_activity?(activity, user, options) do
|
||||||
Logger.warning(
|
Logger.warning(
|
||||||
"Can't check if user #{inspect(user)} can be sent an activity (#{inspect(activity)}) (#{inspect(options)})"
|
"Can't check if user #{inspect(user.email)} can be sent an activity (#{inspect(activity)}) (#{inspect(options)})"
|
||||||
)
|
)
|
||||||
|
|
||||||
false
|
false
|
||||||
|
|
|
@ -51,4 +51,13 @@
|
||||||
})
|
})
|
||||||
|> raw %>
|
|> raw %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% :event_new_participation -> %>
|
||||||
|
<%= dgettext("activity", "%{profile} joined your event %{event}.", %{
|
||||||
|
profile: "<b>#{escaped_display_name_and_username(@activity.author)}</b>",
|
||||||
|
event:
|
||||||
|
"<a href=\"#{Routes.page_url(Mobilizon.Web.Endpoint,
|
||||||
|
:event,
|
||||||
|
@activity.subject_params["event_uuid"]) |> URI.decode()}\">#{escape_html(@activity.subject_params["event_title"])}</a>"
|
||||||
|
})
|
||||||
|
|> raw %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -1,31 +1,37 @@
|
||||||
<%= case @activity.subject do %><% :event_created -> %><%= dgettext("activity", "The event %{event} was created by %{profile}.",
|
<%= case @activity.subject do %><% :event_created -> %><%= dgettext("activity", "The event %{event} was created by %{profile}.",
|
||||||
%{
|
%{
|
||||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
profile: display_name_and_username(@activity.author),
|
||||||
event: @activity.subject_params["event_title"]
|
event: @activity.subject_params["event_title"]
|
||||||
}
|
}
|
||||||
) %>
|
) %>
|
||||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% :event_updated -> %><%= dgettext("activity", "The event %{event} was updated by %{profile}.",
|
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% :event_updated -> %><%= dgettext("activity", "The event %{event} was updated by %{profile}.",
|
||||||
%{
|
%{
|
||||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
profile: display_name_and_username(@activity.author),
|
||||||
event: @activity.subject_params["event_title"]
|
event: @activity.subject_params["event_title"]
|
||||||
}
|
}
|
||||||
) %>
|
) %>
|
||||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% :event_deleted -> %><%= dgettext("activity", "The event %{event} was deleted by %{profile}.",
|
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% :event_deleted -> %><%= dgettext("activity", "The event %{event} was deleted by %{profile}.",
|
||||||
%{
|
%{
|
||||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
profile: display_name_and_username(@activity.author),
|
||||||
event: @activity.subject_params["event_title"]
|
event: @activity.subject_params["event_title"]
|
||||||
}
|
}
|
||||||
) %>
|
) %>
|
||||||
<% :comment_posted -> %><%= if @activity.subject_params["comment_reply_to"] do %><%= dgettext("activity", "%{profile} replied to a comment on the event %{event}.",
|
<% :comment_posted -> %><%= if @activity.subject_params["comment_reply_to"] do %><%= dgettext("activity", "%{profile} replied to a comment on the event %{event}.",
|
||||||
%{
|
%{
|
||||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
profile: display_name_and_username(@activity.author),
|
||||||
event: @activity.subject_params["event_title"]
|
event: @activity.subject_params["event_title"]
|
||||||
}
|
}
|
||||||
) %>
|
) %>
|
||||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% else %><%= dgettext("activity", "%{profile} posted a comment on the event %{event}.",
|
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% else %><%= dgettext("activity", "%{profile} posted a comment on the event %{event}.",
|
||||||
%{
|
%{
|
||||||
profile: Mobilizon.Actors.Actor.display_name_and_username(@activity.author),
|
profile: display_name_and_username(@activity.author),
|
||||||
event: @activity.subject_params["event_title"]
|
event: @activity.subject_params["event_title"]
|
||||||
}
|
}
|
||||||
) %>
|
) %>
|
||||||
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% end %><% end %>
|
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% end %><% :event_new_participation -> %><%= dgettext("activity", "%{profile} joined your event %{event}.",
|
||||||
|
%{
|
||||||
|
profile: display_name_and_username(@activity.author),
|
||||||
|
event: @activity.subject_params["event_title"]
|
||||||
|
}
|
||||||
|
) %>
|
||||||
|
<%= Routes.page_url(Mobilizon.Web.Endpoint, :event, @activity.subject_params["event_uuid"]) |> URI.decode() %><% end %>
|
|
@ -25,7 +25,6 @@ defmodule Mobilizon.Web.EmailView do
|
||||||
defdelegate datetime_relative(datetime, locale \\ "en"), to: DateTimeRenderer
|
defdelegate datetime_relative(datetime, locale \\ "en"), to: DateTimeRenderer
|
||||||
defdelegate render_address(address), to: Address
|
defdelegate render_address(address), to: Address
|
||||||
defdelegate is_same_day?(one, two), to: DateTimeRenderer
|
defdelegate is_same_day?(one, two), to: DateTimeRenderer
|
||||||
defdelegate display_name_and_username(actor), to: Actor
|
|
||||||
defdelegate display_name(actor), to: Actor
|
defdelegate display_name(actor), to: Actor
|
||||||
defdelegate preferred_username_and_domain(actor), to: Actor
|
defdelegate preferred_username_and_domain(actor), to: Actor
|
||||||
|
|
||||||
|
@ -38,7 +37,13 @@ defmodule Mobilizon.Web.EmailView do
|
||||||
|
|
||||||
def escaped_display_name_and_username(actor) do
|
def escaped_display_name_and_username(actor) do
|
||||||
actor
|
actor
|
||||||
|> Actor.display_name_and_username()
|
|> display_name_and_username()
|
||||||
|> escape_html()
|
|> escape_html()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def display_name_and_username(%Actor{preferred_username: "anonymous"}) do
|
||||||
|
dgettext("activity", "An anonymous profile")
|
||||||
|
end
|
||||||
|
|
||||||
|
def display_name_and_username(actor), do: Actor.display_name_and_username(actor)
|
||||||
end
|
end
|
||||||
|
|
149
test/graphql/resolvers/push_subscription_test.exs
Normal file
149
test/graphql/resolvers/push_subscription_test.exs
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
defmodule Mobilizon.GraphQL.Resolvers.PushSubscriptionTest do
|
||||||
|
use Mobilizon.Web.ConnCase
|
||||||
|
|
||||||
|
import Mobilizon.Factory
|
||||||
|
|
||||||
|
alias Mobilizon.GraphQL.AbsintheHelpers
|
||||||
|
|
||||||
|
describe "create a new push subscription" do
|
||||||
|
@register_push_mutation """
|
||||||
|
mutation RegisterPush($endpoint: String!, $auth: String!, $p256dh: String!) {
|
||||||
|
registerPush(endpoint: $endpoint, auth: $auth, p256dh: $p256dh)
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
test "without auth", %{conn: conn} do
|
||||||
|
res =
|
||||||
|
AbsintheHelpers.graphql_query(conn,
|
||||||
|
query: @register_push_mutation,
|
||||||
|
variables: %{endpoint: "https://yolo.com/gfjgfd", auth: "gjrigf", p256dh: "gbgof"}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert hd(res["errors"])["status_code"] == 401
|
||||||
|
assert hd(res["errors"])["message"] == "You need to be logged in"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "succeeds", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
res =
|
||||||
|
conn
|
||||||
|
|> auth_conn(user)
|
||||||
|
|> AbsintheHelpers.graphql_query(
|
||||||
|
query: @register_push_mutation,
|
||||||
|
variables: %{endpoint: "https://yolo.com/gfjgfd", auth: "gjrigf", p256dh: "gbgof"}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert res["errors"] == nil
|
||||||
|
assert res["data"]["registerPush"] == "OK"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails on duplicate", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
res =
|
||||||
|
conn
|
||||||
|
|> auth_conn(user)
|
||||||
|
|> AbsintheHelpers.graphql_query(
|
||||||
|
query: @register_push_mutation,
|
||||||
|
variables: %{
|
||||||
|
endpoint: "https://yolo.com/duplicate",
|
||||||
|
auth: "duplicate",
|
||||||
|
p256dh: "duplicate"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert res["errors"] == nil
|
||||||
|
assert res["data"]["registerPush"] == "OK"
|
||||||
|
|
||||||
|
res =
|
||||||
|
conn
|
||||||
|
|> auth_conn(user)
|
||||||
|
|> AbsintheHelpers.graphql_query(
|
||||||
|
query: @register_push_mutation,
|
||||||
|
variables: %{
|
||||||
|
endpoint: "https://yolo.com/duplicate",
|
||||||
|
auth: "duplicate",
|
||||||
|
p256dh: "duplicate"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert hd(res["errors"])["message"] ==
|
||||||
|
"The same push subscription has already been registered"
|
||||||
|
|
||||||
|
refute res["data"]["registerPush"] == "OK"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "unregister a push subscription" do
|
||||||
|
@unregister_push_mutation """
|
||||||
|
mutation UnRegisterPush($endpoint: String!) {
|
||||||
|
unregisterPush(endpoint: $endpoint)
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
test "without auth", %{conn: conn} do
|
||||||
|
res =
|
||||||
|
AbsintheHelpers.graphql_query(conn,
|
||||||
|
query: @unregister_push_mutation,
|
||||||
|
variables: %{endpoint: "https://yolo.com/gfjgfd"}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert hd(res["errors"])["status_code"] == 401
|
||||||
|
assert hd(res["errors"])["message"] == "You need to be logged in"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails when not existing", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
res =
|
||||||
|
conn
|
||||||
|
|> auth_conn(user)
|
||||||
|
|> AbsintheHelpers.graphql_query(
|
||||||
|
query: @unregister_push_mutation,
|
||||||
|
variables: %{
|
||||||
|
endpoint: "https://yolo.com/duplicate",
|
||||||
|
auth: "duplicate",
|
||||||
|
p256dh: "duplicate"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert hd(res["errors"])["status_code"] == 404
|
||||||
|
assert hd(res["errors"])["message"] == "Resource not found"
|
||||||
|
refute res["data"]["registerPush"] == "OK"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails when wrong user", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
push_subscription = insert(:push_subscription)
|
||||||
|
|
||||||
|
res =
|
||||||
|
conn
|
||||||
|
|> auth_conn(user)
|
||||||
|
|> AbsintheHelpers.graphql_query(
|
||||||
|
query: @unregister_push_mutation,
|
||||||
|
variables: %{endpoint: push_subscription.endpoint}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert hd(res["errors"])["status_code"] == 403
|
||||||
|
assert hd(res["errors"])["message"] == "You don't have permission to do this"
|
||||||
|
refute res["data"]["registerPush"] == "OK"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "succeeds", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
push_subscription = insert(:push_subscription, user: user)
|
||||||
|
|
||||||
|
res =
|
||||||
|
conn
|
||||||
|
|> auth_conn(user)
|
||||||
|
|> AbsintheHelpers.graphql_query(
|
||||||
|
query: @unregister_push_mutation,
|
||||||
|
variables: %{endpoint: push_subscription.endpoint}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert res["errors"] == nil
|
||||||
|
assert res["data"]["unregisterPush"] == "OK"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,24 +5,28 @@ defmodule Mobilizon.Service.Export.Participants.CommonTest do
|
||||||
|
|
||||||
alias Mobilizon.Actors.Actor
|
alias Mobilizon.Actors.Actor
|
||||||
alias Mobilizon.Service.Export.Participants.Common
|
alias Mobilizon.Service.Export.Participants.Common
|
||||||
|
import Mobilizon.Service.DateTime, only: [datetime_to_string: 1]
|
||||||
|
|
||||||
test "convert participants to list items" do
|
test "convert participants to list items" do
|
||||||
participant = insert(:participant)
|
participant = insert(:participant)
|
||||||
actor = insert(:actor)
|
actor = insert(:actor)
|
||||||
name = Actor.display_name_and_username(actor)
|
name = Actor.display_name_and_username(actor)
|
||||||
assert [^name, _, ""] = Common.to_list({participant, actor})
|
date = datetime_to_string(participant.inserted_at)
|
||||||
|
assert [^name, _, ^date, ""] = Common.to_list({participant, actor})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "convert participants with metadata to list items" do
|
test "convert participants with metadata to list items" do
|
||||||
participant = insert(:participant, metadata: %{message: "a message"})
|
participant = insert(:participant, metadata: %{message: "a message"})
|
||||||
actor = insert(:actor)
|
actor = insert(:actor)
|
||||||
name = Actor.display_name_and_username(actor)
|
name = Actor.display_name_and_username(actor)
|
||||||
assert [^name, _, "a message"] = Common.to_list({participant, actor})
|
date = datetime_to_string(participant.inserted_at)
|
||||||
|
assert [^name, _, ^date, "a message"] = Common.to_list({participant, actor})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "convert anonymous participants to list items" do
|
test "convert anonymous participants to list items" do
|
||||||
participant = insert(:participant)
|
participant = insert(:participant)
|
||||||
actor = insert(:actor, domain: nil, preferred_username: "anonymous")
|
actor = insert(:actor, domain: nil, preferred_username: "anonymous")
|
||||||
assert ["Anonymous participant", _, ""] = Common.to_list({participant, actor})
|
date = datetime_to_string(participant.inserted_at)
|
||||||
|
assert ["Anonymous participant", _, ^date, ""] = Common.to_list({participant, actor})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue