diff --git a/README.md b/README.md index 831e17974..04b001093 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ There's no lock-in, you can interact with the event without registration. ## Contributing -We appreciate any contribution to Mobilizon. Check our [CONTRIBUTING](CONTRIBUTING.md) file for more information. +We appreciate any contribution to Mobilizon. Check [our contributing page](https://docs.joinmobilizon.org/contribute/) for more information. ## Links diff --git a/js/src/graphql/followers.ts b/js/src/graphql/followers.ts index c64d208ec..41b775bca 100644 --- a/js/src/graphql/followers.ts +++ b/js/src/graphql/followers.ts @@ -32,7 +32,7 @@ export const GROUP_FOLLOWERS = gql` `; export const UPDATE_FOLLOWER = gql` - mutation UpdateFollower($id: ID!, $approved: Boolean) { + mutation UpdateFollower($id: ID!, $approved: Boolean!) { updateFollower(id: $id, approved: $approved) { id approved diff --git a/js/src/i18n/en_US.json b/js/src/i18n/en_US.json index d319d7acf..531269930 100644 --- a/js/src/i18n/en_US.json +++ b/js/src/i18n/en_US.json @@ -1446,5 +1446,7 @@ "By car": "By car", "Select all resources": "Select all resources", "Select this resource": "Select this resource", - "You can add resources by using the button above.": "You can add resources by using the button above." + "You can add resources by using the button above.": "You can add resources by using the button above.", + "{user}'s follow request was accepted": "{user}'s follow request was accepted", + "{user}'s follow request was rejected": "{user}'s follow request was rejected" } \ No newline at end of file diff --git a/js/src/i18n/fr_FR.json b/js/src/i18n/fr_FR.json index 66f9adf9d..73804da20 100644 --- a/js/src/i18n/fr_FR.json +++ b/js/src/i18n/fr_FR.json @@ -1443,5 +1443,7 @@ "By car": "En voiture", "Select all resources": "Sélectionner toutes les ressources", "Select this resource": "Sélectionner cette ressource", - "You can add resources by using the button above.": "Vous pouvez ajouter des ressources en utilisant le bouton au dessus." + "You can add resources by using the button above.": "Vous pouvez ajouter des ressources en utilisant le bouton au dessus.", + "{user}'s follow request was accepted": "La demande de suivi de {user} a été acceptée", + "{user}'s follow request was rejected": "La demande de suivi de {user} a été rejetée" } diff --git a/js/src/views/Event/EditView.vue b/js/src/views/Event/EditView.vue index dd6b2cfff..ddb78ce9a 100644 --- a/js/src/views/Event/EditView.vue +++ b/js/src/views/Event/EditView.vue @@ -1297,9 +1297,11 @@ const maximumAttendeeCapacity = computed({ return eventOptions.value.maximumAttendeeCapacity.toString(); }, set(newMaximumAttendeeCapacity: string) { - eventOptions.value.maximumAttendeeCapacity = parseInt(newMaximumAttendeeCapacity); - } -}) + eventOptions.value.maximumAttendeeCapacity = parseInt( + newMaximumAttendeeCapacity + ); + }, +}); const dateFnsLocale = inject("dateFnsLocale"); diff --git a/js/src/views/Event/EventView.vue b/js/src/views/Event/EventView.vue index c65e1b852..ca58324d2 100755 --- a/js/src/views/Event/EventView.vue +++ b/js/src/views/Event/EventView.vue @@ -298,7 +298,7 @@ const props = defineProps<{ const { t } = useI18n({ useScope: "global" }); -const propsUUID = computed(() => props.uuid) +const propsUUID = computed(() => props.uuid); const { event, @@ -308,8 +308,8 @@ const { } = useFetchEvent(props.uuid); watch(propsUUID, (newUUid) => { - refetchEvent({ uuid: newUUid }) -}) + refetchEvent({ uuid: newUUid }); +}); const eventId = computed(() => event.value?.id); const { currentActor } = useCurrentActorClient(); diff --git a/js/src/views/Group/GroupFollowers.vue b/js/src/views/Group/GroupFollowers.vue index f54c68ed3..12307d38d 100644 --- a/js/src/views/Group/GroupFollowers.vue +++ b/js/src/views/Group/GroupFollowers.vue @@ -11,12 +11,12 @@ { name: RouteName.GROUP_SETTINGS, params: { preferredUsername: usernameWithDomain(group) }, - text: $t('Settings'), + text: t('Settings'), }, { name: RouteName.GROUP_FOLLOWERS_SETTINGS, params: { preferredUsername: usernameWithDomain(group) }, - text: $t('Followers'), + text: t('Followers'), }, ]" /> @@ -25,9 +25,9 @@ class="container mx-auto section" v-if="group && isCurrentActorAGroupAdmin && followers" > -

{{ $t("Group Followers") }} ({{ followers.total }})

- - {{ $t("Pending") }} +

{{ t("Group Followers") }} ({{ followers.total }})

+ + {{ t("Pending") }}
@@ -76,39 +76,39 @@
- + {{ formatDateString(props.row.insertedAt) }}
{{ formatTimeString(props.row.insertedAt) }}
- -
+ +
{{ $t("Accept") }}{{ t("Accept") }} {{ $t("Reject") }}{{ t("Reject") }}
- {{ $t("You are not an administrator for this group.") }} + {{ t("You are not an administrator for this group.") }}
@@ -164,6 +164,7 @@ const { t } = useI18n({ useScope: "global" }); useHead({ title: computed(() => t("Group Followers")) }); const loadMoreFollowers = async (): Promise => { + console.debug("load more followers"); await fetchMore({ // New variables variables: { @@ -183,6 +184,12 @@ const { onDone, onError, mutate } = useMutation<{ updateFollower: IFollower }>( refetchQueries: [ { query: GROUP_FOLLOWERS, + variables: { + name: usernameWithDomain(group.value), + followersPage: page.value, + followersLimit: FOLLOWERS_PER_PAGE, + approved: !pending.value, + }, }, ], }) @@ -192,11 +199,11 @@ onDone(({ data }) => { const follower = data?.updateFollower; const message = data?.updateFollower.approved === true - ? t("@{username}'s follow request was accepted", { - username: follower?.actor.preferredUsername, + ? t("{user}'s follow request was accepted", { + user: displayName(follower?.actor), }) - : t("@{username}'s follow request was rejected", { - username: follower?.actor.preferredUsername, + : t("{user}'s follow request was rejected", { + user: displayName(follower?.actor), }); notifier?.success(message); }); diff --git a/lib/web/controllers/activity_pub_controller.ex b/lib/web/controllers/activity_pub_controller.ex index 296d774db..93f132826 100644 --- a/lib/web/controllers/activity_pub_controller.ex +++ b/lib/web/controllers/activity_pub_controller.ex @@ -191,6 +191,7 @@ defmodule Mobilizon.Web.ActivityPubController do defp actor_collection(conn, collection, %{"name" => name, "page" => page}) do with {page, ""} <- Integer.parse(page), + page <- max(page, 1), %Actor{} = actor <- Actors.get_local_actor_by_name_with_preload(name) do conn |> put_resp_header("content-type", "application/activity+json") diff --git a/test/web/controllers/activity_pub_controller_test.exs b/test/web/controllers/activity_pub_controller_test.exs index 95367865c..d44ddeefa 100644 --- a/test/web/controllers/activity_pub_controller_test.exs +++ b/test/web/controllers/activity_pub_controller_test.exs @@ -243,6 +243,34 @@ defmodule Mobilizon.Web.ActivityPubControllerTest do assert length(result["orderedItems"]) == 5 end + test "it can't be called for a page < 1", %{conn: conn} do + actor = insert(:actor, visibility: :public) + + Enum.each(1..15, fn _ -> + insert(:event, organizer_actor: actor) + end) + + result = + conn + |> get(Actor.build_url(actor.preferred_username, :outbox)) + |> json_response(200) + + assert length(result["first"]["orderedItems"]) == 10 + assert result["totalItems"] == 15 + + page_0_result = + conn + |> get(Actor.build_url(actor.preferred_username, :outbox, page: 0)) + |> json_response(200) + + page_1_result = + conn + |> get(Actor.build_url(actor.preferred_username, :outbox, page: 1)) + |> json_response(200) + + assert page_0_result == page_1_result + end + test "it returns an empty collection if the actor has private visibility", %{conn: conn} do actor = insert(:actor, visibility: :private) insert(:event, organizer_actor: actor)