diff --git a/js/src/graphql/group.ts b/js/src/graphql/group.ts index 0b1d60874..b53ac350a 100644 --- a/js/src/graphql/group.ts +++ b/js/src/graphql/group.ts @@ -295,6 +295,10 @@ export const CREATE_GROUP = gql` $summary: String $avatar: MediaInput $banner: MediaInput + $physicalAddress: AddressInput + $visibility: GroupVisibility + $openness: Openness + $manuallyApprovesFollowers: Boolean ) { createGroup( preferredUsername: $preferredUsername @@ -302,6 +306,10 @@ export const CREATE_GROUP = gql` summary: $summary banner: $banner avatar: $avatar + physicalAddress: $physicalAddress + visibility: $visibility + openness: $openness + manuallyApprovesFollowers: $manuallyApprovesFollowers ) { ...ActorFragment banner { diff --git a/js/src/types/actor/group.model.ts b/js/src/types/actor/group.model.ts index 26e20449a..e96dc485c 100644 --- a/js/src/types/actor/group.model.ts +++ b/js/src/types/actor/group.model.ts @@ -5,8 +5,7 @@ import type { IResource } from "../resource"; import type { IEvent } from "../event.model"; import type { IDiscussion } from "../discussions"; import type { IPost } from "../post.model"; -import type { IAddress } from "../address.model"; -import { Address } from "../address.model"; +import { Address, type IAddress } from "../address.model"; import { ActorType, GroupVisibility, Openness } from "../enums"; import type { IMember } from "./member.model"; import type { ITodoList } from "../todolist"; @@ -53,11 +52,11 @@ export class Group extends Actor implements IGroup { visibility: GroupVisibility = GroupVisibility.PUBLIC; activity: Paginate = { elements: [], total: 0 }; - openness: Openness = Openness.INVITE_ONLY; + openness: Openness = Openness.MODERATED; physicalAddress: IAddress = new Address(); - manuallyApprovesFollowers = true; + manuallyApprovesFollowers = false; patch(hash: IGroup | Record): void { Object.assign(this, hash); diff --git a/js/src/views/Admin/GroupProfiles.vue b/js/src/views/Admin/GroupProfiles.vue index 7b12c9cb1..21ab50f32 100644 --- a/js/src/views/Admin/GroupProfiles.vue +++ b/js/src/views/Admin/GroupProfiles.vue @@ -120,7 +120,7 @@ import { } from "vue-use-route-query"; import { useI18n } from "vue-i18n"; import { useHead } from "@vueuse/head"; -import { computed, ref } from "vue"; +import { computed } from "vue"; import { Paginate } from "@/types/paginate"; import { IGroup } from "@/types/actor"; import AccountGroup from "vue-material-design-icons/AccountGroup.vue"; diff --git a/js/src/views/Group/CreateView.vue b/js/src/views/Group/CreateView.vue index 6d231376b..d3d9aaed8 100644 --- a/js/src/views/Group/CreateView.vue +++ b/js/src/views/Group/CreateView.vue @@ -69,11 +69,25 @@ :message="summaryErrors[0]" :type="summaryErrors[1]" > - + -
- {{ t("Avatar") }} + + +
+ {{ t("Avatar") }}
-
- {{ t("Banner") }} +
+ {{ t("Banner") }}
- +
+ + {{ t("Group visibility") }} + + + {{ $t("Visible everywhere on the web") }}
+ {{ + $t( + "The group will be publicly listed in search results and may be suggested in the explore section. Only public informations will be shown on it's page." + ) + }} +
+ {{ $t("Only accessible through link") }}
+ {{ + $t( + "You'll need to transmit the group URL so people may access the group's profile. The group won't be findable in Mobilizon's search or regular search engines." + ) + }} +
+
+
+ + {{ t("New members") }} + + {{ + t( + "Members will also access private sections like discussions, resources and restricted posts." + ) + }} + + + + + {{ $t("Anyone can join freely") }}
+ {{ + $t( + "Anyone wanting to be a member from your group will be able to from your group page." + ) + }} +
+
+ + {{ $t("Moderate new members") }}
+ {{ + $t( + "Anyone can request being a member, but an administrator needs to approve the membership." + ) + }} +
+
+ + {{ $t("Manually invite new members") }}
+ {{ + $t( + "The only way for your group to get new members is if an admininistrator invites them." + ) + }} +
+
+
+
+ + + {{ t("Followers") }} + + + {{ t("Followers will receive new public events and posts.") }} + + + + {{ t("Manually approve new followers") }} + +
+ + {{ t("Create my group") }} @@ -105,7 +213,14 @@ import PictureUpload from "../../components/PictureUpload.vue"; import { ErrorResponse } from "@/types/errors.model"; import { ServerParseError } from "@apollo/client/link/http"; import { useCurrentActorClient } from "@/composition/apollo/actor"; -import { computed, inject, reactive, ref, watch } from "vue"; +import { + computed, + defineAsyncComponent, + inject, + reactive, + ref, + watch, +} from "vue"; import { useRouter } from "vue-router"; import { useI18n } from "vue-i18n"; import { useCreateGroup } from "@/composition/apollo/group"; @@ -116,6 +231,12 @@ import { } from "@/composition/config"; import { Notifier } from "@/plugins/notifier"; import { useHead } from "@vueuse/head"; +import { Openness, GroupVisibility } from "@/types/enums"; +import FullAddressAutoComplete from "@/components/Event/FullAddressAutoComplete.vue"; + +const Editor = defineAsyncComponent( + () => import("@/components/TextEditor.vue") +); const { currentActor } = useCurrentActorClient(); @@ -156,10 +277,20 @@ const buildVariables = computed(() => { let avatarObj = {}; let bannerObj = {}; + const cloneGroup = group.value; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + delete cloneGroup.physicalAddress.__typename; + delete cloneGroup.physicalAddress.pictureInfo; + const groupBasic = { preferredUsername: group.value.preferredUsername, name: group.value.name, summary: group.value.summary, + physicalAddress: cloneGroup.physicalAddress, + visibility: group.value.visibility, + openness: group.value.openness, + manuallyApprovesFollowers: group.value.manuallyApprovesFollowers, }; if (avatarFile.value) { diff --git a/lib/graphql/schema/actors/group.ex b/lib/graphql/schema/actors/group.ex index 3b0122a11..eed6b889b 100644 --- a/lib/graphql/schema/actors/group.ex +++ b/lib/graphql/schema/actors/group.ex @@ -305,6 +305,10 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do description: "Whether the group can be join freely, with approval or is invite-only." ) + arg(:manually_approves_followers, :boolean, + description: "Whether this group approves new followers manually" + ) + arg(:avatar, :media_input, description: "The avatar for the group, either as an object or directly the ID of an existing media" diff --git a/lib/mobilizon/actors/actor.ex b/lib/mobilizon/actors/actor.ex index 36ec653b8..9db86aab7 100644 --- a/lib/mobilizon/actors/actor.ex +++ b/lib/mobilizon/actors/actor.ex @@ -146,7 +146,8 @@ defmodule Mobilizon.Actors.Actor do :domain, :summary, :visibility, - :openness + :openness, + :manually_approves_followers ] @group_creation_attrs @group_creation_required_attrs ++ @group_creation_optional_attrs