@@ -42,13 +42,13 @@ body {
|
||||
@apply bg-transparent text-black dark:text-white font-semibold py-2 px-4 border border-mbz-bluegreen dark:border-violet-3;
|
||||
}
|
||||
.btn-outlined-success {
|
||||
@apply border-mbz-success hover:bg-mbz-success;
|
||||
@apply border-2 border-mbz-success bg-transparent text-mbz-success hover:bg-mbz-success;
|
||||
}
|
||||
.btn-outlined-warning {
|
||||
@apply bg-transparent border dark:text-white hover:dark:text-slate-900 hover:bg-mbz-warning border-mbz-warning;
|
||||
}
|
||||
.btn-outlined-danger {
|
||||
@apply border-mbz-danger hover:bg-mbz-danger;
|
||||
@apply border-2 bg-transparent border-mbz-danger text-mbz-danger hover:bg-mbz-danger;
|
||||
}
|
||||
.btn-outlined-text {
|
||||
@apply bg-transparent hover:text-slate-900;
|
||||
@@ -161,15 +161,18 @@ body {
|
||||
}
|
||||
|
||||
.dropdown-item-active {
|
||||
@apply bg-white dark:bg-zinc-700 dark:text-zinc-100 text-black;
|
||||
@apply bg-mbz-yellow-500 dark:bg-mbz-yellow-900 dark:text-zinc-100 text-black;
|
||||
}
|
||||
.dropdown-button {
|
||||
@apply inline-flex gap-1;
|
||||
}
|
||||
|
||||
/* Checkbox */
|
||||
|
||||
.checkbox {
|
||||
margin-inline-end: 1rem;
|
||||
}
|
||||
|
||||
.checkbox-check {
|
||||
@apply appearance-none bg-primary border-primary;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<o-inputitems
|
||||
:modelValue="modelValue"
|
||||
:modelValue="modelValueWithDisplayName"
|
||||
@update:modelValue="(val: IActor[]) => $emit('update:modelValue', val)"
|
||||
:data="availableActors"
|
||||
:allow-autocomplete="true"
|
||||
@@ -21,10 +21,10 @@ import { SEARCH_PERSON_AND_GROUPS } from "@/graphql/search";
|
||||
import { IActor, IGroup, IPerson, displayName } from "@/types/actor";
|
||||
import { Paginate } from "@/types/paginate";
|
||||
import { useLazyQuery } from "@vue/apollo-composable";
|
||||
import { ref } from "vue";
|
||||
import { computed, ref } from "vue";
|
||||
import ActorInline from "./ActorInline.vue";
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
modelValue: IActor[];
|
||||
}>();
|
||||
|
||||
@@ -32,6 +32,15 @@ defineEmits<{
|
||||
"update:modelValue": [value: IActor[]];
|
||||
}>();
|
||||
|
||||
const modelValue = computed(() => props.modelValue);
|
||||
|
||||
const modelValueWithDisplayName = computed(() =>
|
||||
modelValue.value.map((actor) => ({
|
||||
...actor,
|
||||
displayName: displayName(actor),
|
||||
}))
|
||||
);
|
||||
|
||||
const {
|
||||
load: loadSearchPersonsAndGroupsQuery,
|
||||
refetch: refetchSearchPersonsAndGroupsQuery,
|
||||
|
||||
@@ -39,8 +39,18 @@
|
||||
v-html="actor.summary"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex pr-2">
|
||||
<Email />
|
||||
<div class="flex pr-2" v-if="actor.type === ActorType.PERSON">
|
||||
<router-link
|
||||
:to="{
|
||||
name: RouteName.CONVERSATION_LIST,
|
||||
query: {
|
||||
newMessage: 'true',
|
||||
personMentions: usernameWithDomain(actor),
|
||||
},
|
||||
}"
|
||||
>
|
||||
<Email />
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div
|
||||
@@ -85,6 +95,8 @@
|
||||
import { displayName, IActor, usernameWithDomain } from "../../types/actor";
|
||||
import AccountCircle from "vue-material-design-icons/AccountCircle.vue";
|
||||
import Email from "vue-material-design-icons/Email.vue";
|
||||
import RouteName from "@/router/name";
|
||||
import { ActorType } from "@/types/enums";
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
|
||||
@@ -24,15 +24,11 @@
|
||||
@{{ usernameWithDomain(actor) }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex pr-2 self-center">
|
||||
<Email />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { displayName, IActor, usernameWithDomain } from "../../types/actor";
|
||||
import AccountCircle from "vue-material-design-icons/AccountCircle.vue";
|
||||
import Email from "vue-material-design-icons/Email.vue";
|
||||
|
||||
defineProps<{
|
||||
actor: IActor;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<router-link
|
||||
class="flex gap-2 w-full items-center px-2 py-4 border-b-stone-200 border-b bg-white dark:bg-transparent"
|
||||
class="flex gap-4 w-full items-center px-2 py-4 border-b-stone-200 border-b bg-white dark:bg-transparent"
|
||||
dir="auto"
|
||||
:to="{
|
||||
name: RouteName.CONVERSATION,
|
||||
|
||||
@@ -9,6 +9,15 @@
|
||||
:currentActor="currentActor"
|
||||
:placeholder="t('Write a new message')"
|
||||
/>
|
||||
<o-notification
|
||||
class="my-2"
|
||||
variant="danger"
|
||||
:closable="false"
|
||||
v-for="error in errors"
|
||||
:key="error"
|
||||
>
|
||||
{{ error }}
|
||||
</o-notification>
|
||||
<footer class="flex gap-2 py-3 mx-2 justify-end">
|
||||
<o-button :disabled="!canSend" nativeType="submit">{{
|
||||
t("Send")
|
||||
@@ -18,13 +27,14 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { IActor, IPerson, usernameWithDomain } from "@/types/actor";
|
||||
import { IActor, IGroup, IPerson, usernameWithDomain } from "@/types/actor";
|
||||
import { computed, defineAsyncComponent, provide, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import ActorAutoComplete from "../../components/Account/ActorAutoComplete.vue";
|
||||
import {
|
||||
DefaultApolloClient,
|
||||
provideApolloClient,
|
||||
useLazyQuery,
|
||||
useMutation,
|
||||
} from "@vue/apollo-composable";
|
||||
import { apolloClient } from "@/vue-apollo";
|
||||
@@ -34,12 +44,15 @@ import { IConversation } from "@/types/conversation";
|
||||
import { useCurrentActorClient } from "@/composition/apollo/actor";
|
||||
import { useRouter } from "vue-router";
|
||||
import RouteName from "@/router/name";
|
||||
import { FETCH_PERSON } from "@/graphql/actor";
|
||||
import { FETCH_GROUP_PUBLIC } from "@/graphql/group";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
mentions?: IActor[];
|
||||
personMentions?: string[];
|
||||
groupMentions?: string[];
|
||||
}>(),
|
||||
{ mentions: () => [] }
|
||||
{ personMentions: () => [], groupMentions: () => [] }
|
||||
);
|
||||
|
||||
provide(DefaultApolloClient, apolloClient);
|
||||
@@ -48,15 +61,36 @@ const router = useRouter();
|
||||
|
||||
const emit = defineEmits(["close"]);
|
||||
|
||||
const actorMentions = ref(props.mentions);
|
||||
const errors = ref<string[]>([]);
|
||||
|
||||
const textMentions = computed(() =>
|
||||
(props.mentions ?? []).map((actor) => usernameWithDomain(actor)).join(" ")
|
||||
const textPersonMentions = computed(() => props.personMentions);
|
||||
const textGroupMentions = computed(() => props.groupMentions);
|
||||
const actorMentions = ref<IActor[]>([]);
|
||||
|
||||
const { load: fetchPerson } = provideApolloClient(apolloClient)(() =>
|
||||
useLazyQuery<{ fetchPerson: IPerson }, { username: string }>(FETCH_PERSON)
|
||||
);
|
||||
const { load: fetchGroup } = provideApolloClient(apolloClient)(() =>
|
||||
useLazyQuery<{ group: IGroup }, { name: string }>(FETCH_GROUP_PUBLIC)
|
||||
);
|
||||
textPersonMentions.value.forEach(async (textPersonMention) => {
|
||||
const result = await fetchPerson(FETCH_PERSON, {
|
||||
username: textPersonMention,
|
||||
});
|
||||
if (!result) return;
|
||||
actorMentions.value.push(result.fetchPerson);
|
||||
});
|
||||
textGroupMentions.value.forEach(async (textGroupMention) => {
|
||||
const result = await fetchGroup(FETCH_GROUP_PUBLIC, {
|
||||
name: textGroupMention,
|
||||
});
|
||||
if (!result) return;
|
||||
actorMentions.value.push(result.group);
|
||||
});
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
const text = ref(textMentions.value);
|
||||
const text = ref("");
|
||||
|
||||
const Editor = defineAsyncComponent(
|
||||
() => import("../../components/TextEditor.vue")
|
||||
@@ -70,8 +104,8 @@ const canSend = computed(() => {
|
||||
return actorMentions.value.length > 0 || /@.+/.test(text.value);
|
||||
});
|
||||
|
||||
const { mutate: postPrivateMessageMutate } = provideApolloClient(apolloClient)(
|
||||
() =>
|
||||
const { mutate: postPrivateMessageMutate, onError: onPrivateMessageError } =
|
||||
provideApolloClient(apolloClient)(() =>
|
||||
useMutation<
|
||||
{
|
||||
postPrivateMessage: IConversation;
|
||||
@@ -116,7 +150,13 @@ const { mutate: postPrivateMessageMutate } = provideApolloClient(apolloClient)(
|
||||
});
|
||||
},
|
||||
})
|
||||
);
|
||||
);
|
||||
|
||||
onPrivateMessageError((err) => {
|
||||
err.graphQLErrors.forEach((error) => {
|
||||
errors.value.push(error.message);
|
||||
});
|
||||
});
|
||||
|
||||
const sendForm = async (e: Event) => {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -1,5 +1,30 @@
|
||||
<template>
|
||||
<form @submit="sendForm">
|
||||
<h2>{{ t("New announcement") }}</h2>
|
||||
<p>
|
||||
{{
|
||||
t(
|
||||
"This announcement will be send to all participants with the statuses selected below. They will not be allowed to reply to your announcement, but they can create a new conversation with you."
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
<o-field class="mt-2 mb-4">
|
||||
<o-checkbox
|
||||
v-model="selectedRoles"
|
||||
:native-value="ParticipantRole.PARTICIPANT"
|
||||
:label="t('Participant')"
|
||||
/>
|
||||
<o-checkbox
|
||||
v-model="selectedRoles"
|
||||
:native-value="ParticipantRole.NOT_APPROVED"
|
||||
:label="t('Not approved')"
|
||||
/>
|
||||
<o-checkbox
|
||||
v-model="selectedRoles"
|
||||
:native-value="ParticipantRole.REJECTED"
|
||||
:label="t('Rejected')"
|
||||
/>
|
||||
</o-field>
|
||||
<Editor
|
||||
v-model="text"
|
||||
mode="basic"
|
||||
@@ -8,6 +33,15 @@
|
||||
:currentActor="currentActor"
|
||||
:placeholder="t('Write a new message')"
|
||||
/>
|
||||
<o-notification
|
||||
class="my-2"
|
||||
variant="danger"
|
||||
:closable="true"
|
||||
v-for="error in errors"
|
||||
:key="error"
|
||||
>
|
||||
{{ error }}
|
||||
</o-notification>
|
||||
<o-button class="mt-3" nativeType="submit">{{ t("Send") }}</o-button>
|
||||
</form>
|
||||
</template>
|
||||
@@ -32,9 +66,15 @@ const props = defineProps<{
|
||||
const event = computed(() => props.event);
|
||||
|
||||
const text = ref("");
|
||||
|
||||
const errors = ref<string[]>([]);
|
||||
|
||||
const selectedRoles = ref<ParticipantRole[]>([ParticipantRole.PARTICIPANT]);
|
||||
|
||||
const {
|
||||
mutate: eventPrivateMessageMutate,
|
||||
onDone: onEventPrivateMessageMutated,
|
||||
onError: onEventPrivateMessageError,
|
||||
} = useMutation<
|
||||
{
|
||||
sendEventPrivateMessage: IConversation;
|
||||
@@ -43,8 +83,7 @@ const {
|
||||
text: string;
|
||||
actorId: string;
|
||||
eventId: string;
|
||||
roles?: string;
|
||||
inReplyToActorId?: ParticipantRole[];
|
||||
roles?: ParticipantRole[];
|
||||
language?: string;
|
||||
}
|
||||
>(SEND_EVENT_PRIVATE_MESSAGE_MUTATION, {
|
||||
@@ -96,6 +135,7 @@ const sendForm = (e: Event) => {
|
||||
event.value.organizerActor?.id ??
|
||||
currentActor.value?.id,
|
||||
eventId: event.value.id,
|
||||
roles: selectedRoles.value,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -103,6 +143,12 @@ onEventPrivateMessageMutated(() => {
|
||||
text.value = "";
|
||||
});
|
||||
|
||||
onEventPrivateMessageError((err) => {
|
||||
err.graphQLErrors.forEach((error) => {
|
||||
errors.value.push(error.message);
|
||||
});
|
||||
});
|
||||
|
||||
const Editor = defineAsyncComponent(
|
||||
() => import("../../components/TextEditor.vue")
|
||||
);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<router-link :to="{ name: RouteName.EVENT_PARTICIPATE_WITH_ACCOUNT }">
|
||||
<figure class="flex justify-center my-2">
|
||||
<img
|
||||
src="../../../public/img/undraw_profile.svg"
|
||||
src="/img/undraw_profile.svg"
|
||||
alt="Profile illustration"
|
||||
width="128"
|
||||
height="128"
|
||||
@@ -55,7 +55,7 @@
|
||||
<img
|
||||
width="128"
|
||||
height="128"
|
||||
src="../../../public/img/undraw_mail_2.svg"
|
||||
src="/img/undraw_mail_2.svg"
|
||||
alt="Privacy illustration"
|
||||
/>
|
||||
</figure>
|
||||
@@ -66,7 +66,7 @@
|
||||
<a :href="`${event.url}/participate/without-account`" v-else>
|
||||
<figure class="flex justify-center my-2">
|
||||
<img
|
||||
src="../../../public/img/undraw_mail_2.svg"
|
||||
src="/img/undraw_mail_2.svg"
|
||||
width="128"
|
||||
height="128"
|
||||
alt="Privacy illustration"
|
||||
|
||||
@@ -54,7 +54,6 @@ export const SEND_EVENT_PRIVATE_MESSAGE_MUTATION = gql`
|
||||
$actorId: ID!
|
||||
$eventId: ID!
|
||||
$roles: [ParticipantRoleEnum]
|
||||
$attributedToId: ID
|
||||
$language: String
|
||||
) {
|
||||
sendEventPrivateMessage(
|
||||
@@ -62,7 +61,6 @@ export const SEND_EVENT_PRIVATE_MESSAGE_MUTATION = gql`
|
||||
actorId: $actorId
|
||||
eventId: $eventId
|
||||
roles: $roles
|
||||
attributedToId: $attributedToId
|
||||
language: $language
|
||||
) {
|
||||
...ConversationQuery
|
||||
|
||||
@@ -1625,5 +1625,8 @@
|
||||
"You have access to this conversation as a member of the {group} group": "You have access to this conversation as a member of the {group} group",
|
||||
"Comment from an event announcement": "Comment from an event announcement",
|
||||
"Comment from a private conversation": "Comment from a private conversation",
|
||||
"I've been mentionned in a conversation": "I've been mentionned in a conversation"
|
||||
"I've been mentionned in a conversation": "I've been mentionned in a conversation",
|
||||
"New announcement": "New announcement",
|
||||
"This announcement will be send to all participants with the statuses selected below. They will not be allowed to reply to your announcement, but they can create a new conversation with you.": "This announcement will be send to all participants with the statuses selected below. They will not be allowed to reply to your announcement, but they can create a new conversation with you.",
|
||||
"The following participants are groups, which means group members are able to reply to this conversation:": "The following participants are groups, which means group members are able to reply to this conversation:"
|
||||
}
|
||||
@@ -1621,5 +1621,8 @@
|
||||
"You have access to this conversation as a member of the {group} group": "Vous avez accès à cette conversation en tant que membre du groupe {group}",
|
||||
"Comment from an event announcement": "Commentaire d'une annonce d'événement",
|
||||
"Comment from a private conversation": "Commentaire d'une conversation privée",
|
||||
"I've been mentionned in a conversation": "J'ai été mentionnée dans une conversation"
|
||||
"I've been mentionned in a conversation": "J'ai été mentionnée dans une conversation",
|
||||
"New announcement": "Nouvelle annonce",
|
||||
"This announcement will be send to all participants with the statuses selected below. They will not be allowed to reply to your announcement, but they can create a new conversation with you.": "Cette annonce sera envoyée à tous les participant·es ayant le statut sélectionné ci-dessous. Iels ne pourront pas répondre à votre annonce, mais iels peuvent créer une nouvelle conversation avec vous.",
|
||||
"The following participants are groups, which means group members are able to reply to this conversation:": "Les participants suivants sont des groupes, ce qui signifie que les membres du groupes peuvent répondre dans cette conversation:"
|
||||
}
|
||||
|
||||
@@ -35,7 +35,8 @@ export const orugaConfig = {
|
||||
variantClass: "icon-",
|
||||
},
|
||||
checkbox: {
|
||||
checkClass: "checkbox",
|
||||
rootClass: "checkbox",
|
||||
checkClass: "checkbox-check",
|
||||
checkCheckedClass: "checkbox-checked",
|
||||
labelClass: "checkbox-label",
|
||||
},
|
||||
|
||||
10
src/utils/route.ts
Normal file
10
src/utils/route.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { RouteQueryTransformer } from "vue-use-route-query";
|
||||
|
||||
export const arrayTransformer: RouteQueryTransformer<string[]> = {
|
||||
fromQuery(query: string) {
|
||||
return query.split(",");
|
||||
},
|
||||
toQuery(value: string[]) {
|
||||
return value.join(",");
|
||||
},
|
||||
};
|
||||
@@ -80,7 +80,7 @@
|
||||
<img
|
||||
class="w-12"
|
||||
v-if="instance.hasRelay"
|
||||
src="../../../public/img/logo.svg"
|
||||
src="/img/logo.svg"
|
||||
alt=""
|
||||
/>
|
||||
<CloudQuestion v-else :size="36" />
|
||||
|
||||
@@ -44,19 +44,28 @@
|
||||
<script lang="ts" setup>
|
||||
import RouteName from "../../router/name";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { computed, defineAsyncComponent, ref } from "vue";
|
||||
import { computed, defineAsyncComponent, ref, watchEffect } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { integerTransformer, useRouteQuery } from "vue-use-route-query";
|
||||
import {
|
||||
booleanTransformer,
|
||||
integerTransformer,
|
||||
useRouteQuery,
|
||||
} from "vue-use-route-query";
|
||||
import { PROFILE_CONVERSATIONS } from "@/graphql/event";
|
||||
import ConversationListItem from "../../components/Conversations/ConversationListItem.vue";
|
||||
import EmptyContent from "../../components/Utils/EmptyContent.vue";
|
||||
import { useHead } from "@vueuse/head";
|
||||
import { IPerson } from "@/types/actor";
|
||||
import { useProgrammatic } from "@oruga-ui/oruga-next";
|
||||
import { arrayTransformer } from "@/utils/route";
|
||||
|
||||
const page = useRouteQuery("page", 1, integerTransformer);
|
||||
const CONVERSATIONS_PER_PAGE = 10;
|
||||
|
||||
const showModal = useRouteQuery("newMessage", false, booleanTransformer);
|
||||
const personMentions = useRouteQuery("personMentions", [], arrayTransformer);
|
||||
const groupMentions = useRouteQuery("groupMentions", [], arrayTransformer);
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
useHead({
|
||||
@@ -69,6 +78,7 @@ const { result: conversationsResult } = useQuery<{
|
||||
loggedPerson: Pick<IPerson, "conversations">;
|
||||
}>(PROFILE_CONVERSATIONS, () => ({
|
||||
page: page.value,
|
||||
limit: CONVERSATIONS_PER_PAGE,
|
||||
}));
|
||||
|
||||
const conversations = computed(
|
||||
@@ -88,7 +98,17 @@ const NewConversation = defineAsyncComponent(
|
||||
const openNewMessageModal = () => {
|
||||
oruga.modal.open({
|
||||
component: NewConversation,
|
||||
props: {
|
||||
personMentions: personMentions.value,
|
||||
groupMentions: groupMentions.value,
|
||||
},
|
||||
trapFocus: true,
|
||||
});
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
if (showModal.value) {
|
||||
openNewMessageModal();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
]"
|
||||
/>
|
||||
<div
|
||||
v-if="conversation.event"
|
||||
class="bg-mbz-yellow p-6 mb-6 rounded flex gap-2 items-center"
|
||||
v-if="conversation.event && !isCurrentActorAuthor"
|
||||
class="bg-mbz-yellow p-6 mb-3 rounded flex gap-2 items-center"
|
||||
>
|
||||
<Calendar :size="36" />
|
||||
<i18n-t
|
||||
tag="p"
|
||||
keypath="This is a announcement from the organizers of event {event}"
|
||||
keypath="This is a announcement from the organizers of event {event}. You can't reply to it, but you can send a private message to event organizers."
|
||||
>
|
||||
<template #event>
|
||||
<b>
|
||||
@@ -35,10 +35,7 @@
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div
|
||||
v-if="currentActor && currentActor.id !== conversation.actor?.id"
|
||||
class="bg-mbz-info p-6 rounded flex gap-2 items-center my-3"
|
||||
>
|
||||
<o-notification v-if="isCurrentActorAuthor" variant="info" closable>
|
||||
<i18n-t
|
||||
keypath="You have access to this conversation as a member of the {group} group"
|
||||
tag="p"
|
||||
@@ -55,7 +52,36 @@
|
||||
>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</o-notification>
|
||||
<o-notification
|
||||
v-else-if="groupParticipants.length > 0 && !conversation.event"
|
||||
variant="info"
|
||||
closable
|
||||
>
|
||||
<p>
|
||||
{{
|
||||
t(
|
||||
"The following participants are groups, which means group members are able to reply to this conversation:"
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
<ul class="list-disc">
|
||||
<li
|
||||
v-for="groupParticipant in groupParticipants"
|
||||
:key="groupParticipant.id"
|
||||
>
|
||||
<router-link
|
||||
:to="{
|
||||
name: RouteName.GROUP,
|
||||
params: {
|
||||
preferredUsername: usernameWithDomain(groupParticipant),
|
||||
},
|
||||
}"
|
||||
><b>{{ displayName(groupParticipant) }}</b></router-link
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</o-notification>
|
||||
<o-notification v-if="error" variant="danger">
|
||||
{{ error }}
|
||||
</o-notification>
|
||||
@@ -107,7 +133,7 @@
|
||||
</form>
|
||||
<div
|
||||
v-else-if="conversation.event"
|
||||
class="bg-mbz-yellow p-6 rounded flex gap-2 items-center mt-6"
|
||||
class="bg-mbz-yellow p-6 rounded flex gap-2 items-center mt-3"
|
||||
>
|
||||
<Calendar :size="36" />
|
||||
<i18n-t
|
||||
@@ -239,6 +265,12 @@ const otherParticipants = computed(
|
||||
) ?? []
|
||||
);
|
||||
|
||||
const groupParticipants = computed(() => {
|
||||
return otherParticipants.value.filter(
|
||||
(participant) => participant.type === ActorType.GROUP
|
||||
);
|
||||
});
|
||||
|
||||
const Editor = defineAsyncComponent(
|
||||
() => import("../../components/TextEditor.vue")
|
||||
);
|
||||
@@ -253,8 +285,15 @@ const title = computed(() =>
|
||||
})
|
||||
);
|
||||
|
||||
const isCurrentActorAuthor = computed(
|
||||
() =>
|
||||
currentActor.value &&
|
||||
conversation.value &&
|
||||
currentActor.value.id !== conversation.value?.actor?.id
|
||||
);
|
||||
|
||||
useHead({
|
||||
title: title.value,
|
||||
title: () => title.value,
|
||||
});
|
||||
|
||||
const newComment = ref("");
|
||||
|
||||
@@ -650,12 +650,6 @@ const FullAddressAutoComplete = defineAsyncComponent(
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
useHead({
|
||||
title: computed(() =>
|
||||
props.isUpdate ? t("Event edition") : t("Event creation")
|
||||
),
|
||||
});
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
eventId?: undefined | string;
|
||||
@@ -667,6 +661,12 @@ const props = withDefaults(
|
||||
|
||||
const eventId = computed(() => props.eventId);
|
||||
|
||||
useHead({
|
||||
title: computed(() =>
|
||||
props.isUpdate ? t("Event edition") : t("Event creation")
|
||||
),
|
||||
});
|
||||
|
||||
const event = ref<IEditableEvent>(new EventModel());
|
||||
const unmodifiedEvent = ref<IEditableEvent>(new EventModel());
|
||||
|
||||
|
||||
@@ -225,6 +225,7 @@
|
||||
@click="acceptParticipants(checkedRows)"
|
||||
variant="success"
|
||||
:disabled="!canAcceptParticipants"
|
||||
outlined
|
||||
>
|
||||
{{
|
||||
t(
|
||||
@@ -238,6 +239,7 @@
|
||||
@click="refuseParticipants(checkedRows)"
|
||||
variant="danger"
|
||||
:disabled="!canRefuseParticipants"
|
||||
outlined
|
||||
>
|
||||
{{
|
||||
t(
|
||||
|
||||
@@ -266,6 +266,21 @@
|
||||
: t("Deactivate notifications")
|
||||
}}</span>
|
||||
</o-button>
|
||||
<o-button
|
||||
outlined
|
||||
tag="router-link"
|
||||
:to="{
|
||||
name: RouteName.CONVERSATION_LIST,
|
||||
query: {
|
||||
newMessage: 'true',
|
||||
groupMentions: usernameWithDomain(group),
|
||||
},
|
||||
}"
|
||||
icon-left="email"
|
||||
v-if="!isCurrentActorAGroupMember || previewPublic"
|
||||
>
|
||||
{{ t("Contact") }}
|
||||
</o-button>
|
||||
<o-button
|
||||
outlined
|
||||
icon-left="share"
|
||||
|
||||
@@ -5,19 +5,19 @@
|
||||
<div class="-z-10 overflow-hidden">
|
||||
<img
|
||||
alt=""
|
||||
src="../../public/img/shape-1.svg"
|
||||
src="/img/shape-1.svg"
|
||||
class="-z-10 absolute left-[2%] top-36"
|
||||
width="300"
|
||||
/>
|
||||
<img
|
||||
alt=""
|
||||
src="../../public/img/shape-2.svg"
|
||||
src="/img/shape-2.svg"
|
||||
class="-z-10 absolute left-[50%] top-[5%] -translate-x-2/4 opacity-60"
|
||||
width="800"
|
||||
/>
|
||||
<img
|
||||
alt=""
|
||||
src="../../public/img/shape-3.svg"
|
||||
src="/img/shape-3.svg"
|
||||
class="-z-10 absolute top-0 right-36"
|
||||
width="200"
|
||||
/>
|
||||
|
||||
@@ -749,7 +749,6 @@ import {
|
||||
useRouteQuery,
|
||||
enumTransformer,
|
||||
booleanTransformer,
|
||||
RouteQueryTransformer,
|
||||
} from "vue-use-route-query";
|
||||
import Calendar from "vue-material-design-icons/Calendar.vue";
|
||||
import AccountMultiple from "vue-material-design-icons/AccountMultiple.vue";
|
||||
@@ -776,6 +775,7 @@ import lodashSortBy from "lodash/sortBy";
|
||||
import EmptyContent from "@/components/Utils/EmptyContent.vue";
|
||||
import SkeletonGroupResultList from "@/components/Group/SkeletonGroupResultList.vue";
|
||||
import SkeletonEventResultList from "@/components/Event/SkeletonEventResultList.vue";
|
||||
import { arrayTransformer } from "@/utils/route";
|
||||
|
||||
const EventMarkerMap = defineAsyncComponent(
|
||||
() => import("@/components/Search/EventMarkerMap.vue")
|
||||
@@ -840,15 +840,6 @@ enum SortValues {
|
||||
MEMBER_COUNT_DESC = "MEMBER_COUNT_DESC",
|
||||
}
|
||||
|
||||
const arrayTransformer: RouteQueryTransformer<string[]> = {
|
||||
fromQuery(query: string) {
|
||||
return query.split(",");
|
||||
},
|
||||
toQuery(value: string[]) {
|
||||
return value.join(",");
|
||||
},
|
||||
};
|
||||
|
||||
const props = defineProps<{
|
||||
tag?: string;
|
||||
}>();
|
||||
|
||||
Reference in New Issue
Block a user