all developments of milestone 1
This commit is contained in:
@@ -123,7 +123,7 @@ import { IStatistics } from "../../types/statistics.model";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
|
||||
const { result: configResult } = useQuery<{ config: IConfig }>(ABOUT);
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { ABOUT } from "../../graphql/config";
|
||||
|
||||
@@ -14,7 +14,7 @@ import { PRIVACY } from "@/graphql/config";
|
||||
import { IConfig } from "@/types/config.model";
|
||||
import { InstancePrivacyType } from "@/types/enums";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
import { RULES } from "@/graphql/config";
|
||||
import { IConfig } from "@/types/config.model";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { TERMS } from "@/graphql/config";
|
||||
import { IConfig } from "@/types/config.model";
|
||||
import { InstanceTermsType } from "@/types/enums";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ import { useQuery } from "@vue/apollo-composable";
|
||||
import { computed } from "vue";
|
||||
import { useCurrentUserClient } from "@/composition/apollo/user";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
|
||||
const { currentUser } = useCurrentUserClient();
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ import { useRouter } from "vue-router";
|
||||
import { registerAccount } from "@/composition/apollo/user";
|
||||
import { convertToUsername } from "@/utils/username";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { getValueFromMeta } from "@/utils/html";
|
||||
|
||||
const props = withDefaults(
|
||||
|
||||
@@ -224,7 +224,7 @@ import { Dialog } from "@/plugins/dialog";
|
||||
import { Notifier } from "@/plugins/notifier";
|
||||
import { AbsintheGraphQLErrors } from "@/types/errors.model";
|
||||
import { ICurrentUser } from "@/types/current-user.model";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
const router = useRouter();
|
||||
|
||||
@@ -336,7 +336,7 @@ import EmptyContent from "../../components/Utils/EmptyContent.vue";
|
||||
import { ApolloCache, FetchResult } from "@apollo/client/core";
|
||||
import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { computed, inject } from "vue";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { integerTransformer, useRouteQuery } from "vue-use-route-query";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import {
|
||||
|
||||
@@ -319,7 +319,7 @@ import { MemberRole } from "@/types/enums";
|
||||
import cloneDeep from "lodash/cloneDeep";
|
||||
import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { integerTransformer, useRouteQuery } from "vue-use-route-query";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import {
|
||||
|
||||
@@ -327,7 +327,7 @@ import { ADMIN_UPDATE_USER, LANGUAGES_CODES } from "@/graphql/admin";
|
||||
import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { ILanguage } from "@/types/admin.model";
|
||||
import { computed, inject, reactive, ref, watch } from "vue";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { formatDateTimeString } from "@/filters/datetime";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
@@ -90,7 +90,7 @@ import RouteName from "@/router/name";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import NumberDashboardTile from "@/components/Dashboard/NumberDashboardTile.vue";
|
||||
import LinkedNumberDashboardTile from "@/components/Dashboard/LinkedNumberDashboardTile.vue";
|
||||
import { InstanceFilterFollowStatus } from "@/types/enums";
|
||||
|
||||
@@ -119,7 +119,7 @@ import {
|
||||
useRouteQuery,
|
||||
} from "vue-use-route-query";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed } from "vue";
|
||||
import { Paginate } from "@/types/paginate";
|
||||
import { IGroup } from "@/types/actor";
|
||||
|
||||
@@ -235,7 +235,7 @@ import {
|
||||
import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { computed, inject, ref, watch } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import CloudQuestion from "../../../node_modules/vue-material-design-icons/CloudQuestion.vue";
|
||||
import { Notifier } from "@/plugins/notifier";
|
||||
import MastodonLogo from "@/components/Share/MastodonLogo.vue";
|
||||
|
||||
@@ -103,7 +103,7 @@ import EmptyContent from "@/components/Utils/EmptyContent.vue";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { computed } from "vue";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import {
|
||||
useRouteQuery,
|
||||
booleanTransformer,
|
||||
|
||||
@@ -58,6 +58,70 @@
|
||||
</small>
|
||||
<o-input v-model="settingsToWrite.contact" id="instance-contact" />
|
||||
</div>
|
||||
<label class="field flex flex-col">
|
||||
<p>{{ t("Logo") }}</p>
|
||||
<small>
|
||||
{{
|
||||
t(
|
||||
"Logo of the instance. Defaults to the upstream Mobilizon logo."
|
||||
)
|
||||
}}
|
||||
</small>
|
||||
<picture-upload
|
||||
v-model:modelValue="instanceLogoFile"
|
||||
:defaultImage="settingsToWrite.instanceLogo"
|
||||
:textFallback="t('Logo')"
|
||||
:maxSize="maxSize"
|
||||
/>
|
||||
</label>
|
||||
<label class="field flex flex-col">
|
||||
<p>{{ t("Favicon") }}</p>
|
||||
<small>
|
||||
{{
|
||||
t(
|
||||
"Browser tab icon and PWA icon of the instance. Defaults to the upstream Mobilizon icon."
|
||||
)
|
||||
}}
|
||||
</small>
|
||||
<picture-upload
|
||||
v-model:modelValue="instanceFaviconFile"
|
||||
:defaultImage="settingsToWrite.instanceFavicon"
|
||||
:textFallback="t('Favicon')"
|
||||
:maxSize="maxSize"
|
||||
/>
|
||||
</label>
|
||||
<label class="field flex flex-col">
|
||||
<p>{{ t("Default Picture") }}</p>
|
||||
<small>
|
||||
{{ t("Default picture when an event or group doesn't have one.") }}
|
||||
</small>
|
||||
<picture-upload
|
||||
v-model:modelValue="defaultPictureFile"
|
||||
:defaultImage="settingsToWrite.defaultPicture"
|
||||
:textFallback="t('Default Picture')"
|
||||
:maxSize="maxSize"
|
||||
/>
|
||||
</label>
|
||||
<!-- piece of code to manage instance colors
|
||||
<div class="field flex flex-col">
|
||||
<label class="" for="primary-color">{{ t("Primary Color") }}</label>
|
||||
<o-input
|
||||
type="color"
|
||||
v-model="settingsToWrite.primaryColor"
|
||||
id="primary-color"
|
||||
/>
|
||||
</div>
|
||||
<div class="field flex flex-col">
|
||||
<label class="" for="secondary-color">{{
|
||||
t("Secondary Color")
|
||||
}}</label>
|
||||
<o-input
|
||||
type="color"
|
||||
v-model="settingsToWrite.secondaryColor"
|
||||
id="secondary-color"
|
||||
/>
|
||||
</div>
|
||||
-->
|
||||
<o-field :label="t('Allow registrations')">
|
||||
<o-switch v-model="settingsToWrite.registrationsOpen">
|
||||
<p
|
||||
@@ -389,15 +453,29 @@ import RouteName from "@/router/name";
|
||||
import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { ref, computed, watch, inject } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import type { Notifier } from "@/plugins/notifier";
|
||||
|
||||
// Media upload related
|
||||
import PictureUpload from "@/components/PictureUpload.vue";
|
||||
import {
|
||||
initWrappedMedia,
|
||||
loadWrappedMedia,
|
||||
asMediaInput,
|
||||
} from "@/utils/image";
|
||||
import { useDefaultMaxSize } from "@/composition/config";
|
||||
|
||||
const defaultAdminSettings: IAdminSettings = {
|
||||
instanceName: "",
|
||||
instanceDescription: "",
|
||||
instanceSlogan: "",
|
||||
instanceLongDescription: "",
|
||||
contact: "",
|
||||
instanceLogo: null,
|
||||
instanceFavicon: null,
|
||||
defaultPicture: null,
|
||||
primaryColor: "",
|
||||
secondaryColor: "",
|
||||
instanceTerms: "",
|
||||
instanceTermsType: InstanceTermsType.DEFAULT,
|
||||
instanceTermsUrl: null,
|
||||
@@ -409,12 +487,30 @@ const defaultAdminSettings: IAdminSettings = {
|
||||
instanceLanguages: [],
|
||||
};
|
||||
|
||||
const { result: adminSettingsResult } = useQuery<{
|
||||
const { onResult: onAdminSettingsResult } = useQuery<{
|
||||
adminSettings: IAdminSettings;
|
||||
}>(ADMIN_SETTINGS);
|
||||
const adminSettings = computed(
|
||||
() => adminSettingsResult.value?.adminSettings ?? defaultAdminSettings
|
||||
);
|
||||
|
||||
const adminSettings = ref<IAdminSettings>();
|
||||
|
||||
onAdminSettingsResult(async ({ data }) => {
|
||||
if (!data) return;
|
||||
adminSettings.value =
|
||||
{
|
||||
...data.adminSettings,
|
||||
} ?? defaultAdminSettings;
|
||||
|
||||
loadWrappedMedia(instanceLogo, adminSettings.value.instanceLogo);
|
||||
loadWrappedMedia(instanceFavicon, adminSettings.value.instanceFavicon);
|
||||
loadWrappedMedia(defaultPicture, adminSettings.value.defaultPicture);
|
||||
});
|
||||
|
||||
const instanceLogo = initWrappedMedia();
|
||||
const { file: instanceLogoFile } = instanceLogo;
|
||||
const instanceFavicon = initWrappedMedia();
|
||||
const { file: instanceFaviconFile } = instanceFavicon;
|
||||
const defaultPicture = initWrappedMedia();
|
||||
const { file: defaultPictureFile } = defaultPicture;
|
||||
|
||||
const { result: languageResult } = useQuery<{ languages: ILanguage[] }>(
|
||||
LANGUAGES
|
||||
@@ -463,6 +559,9 @@ const {
|
||||
} = useMutation(SAVE_ADMIN_SETTINGS);
|
||||
|
||||
saveAdminSettingsDone(() => {
|
||||
instanceLogo.firstHash = instanceLogo.hash;
|
||||
instanceFavicon.firstHash = instanceFavicon.hash;
|
||||
defaultPicture.firstHash = defaultPicture.hash;
|
||||
notifier?.success(t("Admin settings successfully saved.") as string);
|
||||
});
|
||||
|
||||
@@ -472,11 +571,29 @@ saveAdminSettingsError((e) => {
|
||||
});
|
||||
|
||||
const updateSettings = async (): Promise<void> => {
|
||||
const variables = { ...settingsToWrite.value };
|
||||
console.debug("updating settings with variables", variables);
|
||||
const variables = {
|
||||
...settingsToWrite.value,
|
||||
...asMediaInput(
|
||||
instanceLogo,
|
||||
"instanceLogo",
|
||||
adminSettings.value?.instanceLogo?.id
|
||||
),
|
||||
...asMediaInput(
|
||||
instanceFavicon,
|
||||
"instanceFavicon",
|
||||
adminSettings.value?.instanceFavicon?.id
|
||||
),
|
||||
...asMediaInput(
|
||||
defaultPicture,
|
||||
"defaultPicture",
|
||||
adminSettings.value?.defaultPicture?.id
|
||||
),
|
||||
};
|
||||
saveAdminSettings(variables);
|
||||
};
|
||||
|
||||
const maxSize = useDefaultMaxSize();
|
||||
|
||||
const getFilteredLanguages = (text: string): void => {
|
||||
filteredLanguages.value = languages.value
|
||||
? languages.value
|
||||
|
||||
@@ -110,7 +110,7 @@ import { useQuery } from "@vue/apollo-composable";
|
||||
import { ILanguage } from "@/types/admin.model";
|
||||
import { computed, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { integerTransformer, useRouteQuery } from "vue-use-route-query";
|
||||
import { formatDateTimeString } from "@/filters/datetime";
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ import {
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useEventCategories } from "@/composition/apollo/config";
|
||||
import EmptyContent from "@/components/Utils/EmptyContent.vue";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ import {
|
||||
import { PROFILE_CONVERSATIONS } from "@/graphql/event";
|
||||
import ConversationListItem from "../../components/Conversations/ConversationListItem.vue";
|
||||
import EmptyContent from "../../components/Utils/EmptyContent.vue";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { IPerson } from "@/types/actor";
|
||||
import { useOruga } from "@oruga-ui/oruga-next";
|
||||
import { arrayTransformer } from "@/utils/route";
|
||||
|
||||
@@ -189,7 +189,7 @@ import {
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
} from "vue";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useCurrentActorClient } from "../../composition/apollo/actor";
|
||||
import { AbsintheGraphQLError } from "../../types/errors.model";
|
||||
|
||||
@@ -70,7 +70,7 @@ import { useI18n } from "vue-i18n";
|
||||
import { useMutation } from "@vue/apollo-composable";
|
||||
import { IDiscussion } from "@/types/discussions";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { Notifier } from "@/plugins/notifier";
|
||||
import { AbsintheGraphQLError } from "@/types/errors.model";
|
||||
|
||||
|
||||
@@ -98,7 +98,6 @@
|
||||
</form>
|
||||
</div>
|
||||
<discussion-comment
|
||||
class="border rounded-md p-2 mt-4"
|
||||
v-for="comment in discussion.comments.elements"
|
||||
:key="comment.id"
|
||||
:model-value="comment"
|
||||
@@ -172,7 +171,7 @@ import {
|
||||
computed,
|
||||
inject,
|
||||
} from "vue";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useCurrentActorClient } from "@/composition/apollo/actor";
|
||||
import { AbsintheGraphQLError } from "@/types/errors.model";
|
||||
@@ -180,6 +179,7 @@ import { MemberRole } from "@/types/enums";
|
||||
import { PERSON_MEMBERSHIPS } from "@/graphql/actor";
|
||||
import { Dialog } from "@/plugins/dialog";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { watch } from "vue";
|
||||
|
||||
const props = defineProps<{ slug: string }>();
|
||||
|
||||
@@ -188,6 +188,8 @@ const COMMENTS_PER_PAGE = 10;
|
||||
|
||||
const { currentActor } = useCurrentActorClient();
|
||||
|
||||
const slug = computed(() => props.slug);
|
||||
|
||||
const {
|
||||
result: discussionResult,
|
||||
onError: onDiscussionError,
|
||||
@@ -197,52 +199,55 @@ const {
|
||||
} = useQuery<{ discussion: IDiscussion }>(
|
||||
GET_DISCUSSION,
|
||||
() => ({
|
||||
slug: props.slug,
|
||||
slug: slug.value,
|
||||
page: page.value,
|
||||
limit: COMMENTS_PER_PAGE,
|
||||
}),
|
||||
() => ({
|
||||
enabled: props.slug !== undefined,
|
||||
enabled: slug.value !== undefined,
|
||||
})
|
||||
);
|
||||
|
||||
subscribeToMore({
|
||||
document: DISCUSSION_COMMENT_CHANGED,
|
||||
variables: () => ({
|
||||
slug: props.slug,
|
||||
page: page.value,
|
||||
limit: COMMENTS_PER_PAGE,
|
||||
}),
|
||||
updateQuery(
|
||||
previousResult: any,
|
||||
{ subscriptionData }: { subscriptionData: any }
|
||||
) {
|
||||
const previousDiscussion = previousResult.discussion;
|
||||
const lastComment =
|
||||
subscriptionData.data.discussionCommentChanged.lastComment;
|
||||
hasMoreComments.value = !previousDiscussion.comments.elements.some(
|
||||
(comment: IComment) => comment.id === lastComment.id
|
||||
);
|
||||
if (hasMoreComments.value) {
|
||||
return {
|
||||
discussion: {
|
||||
...previousDiscussion,
|
||||
lastComment: lastComment,
|
||||
comments: {
|
||||
elements: [
|
||||
...previousDiscussion.comments.elements.filter(
|
||||
({ id }: { id: string }) => id !== lastComment.id
|
||||
),
|
||||
lastComment,
|
||||
],
|
||||
total: previousDiscussion.comments.total + 1,
|
||||
watch(slug, (newSlug: string | undefined | null) => {
|
||||
if (!newSlug) return;
|
||||
subscribeToMore({
|
||||
document: DISCUSSION_COMMENT_CHANGED,
|
||||
variables: () => ({
|
||||
slug: slug.value,
|
||||
page: page.value,
|
||||
limit: COMMENTS_PER_PAGE,
|
||||
}),
|
||||
updateQuery(
|
||||
previousResult: any,
|
||||
{ subscriptionData }: { subscriptionData: any }
|
||||
) {
|
||||
const previousDiscussion = previousResult.discussion;
|
||||
const lastComment =
|
||||
subscriptionData.data.discussionCommentChanged.lastComment;
|
||||
hasMoreComments.value = !previousDiscussion.comments.elements.some(
|
||||
(comment: IComment) => comment.id === lastComment.id
|
||||
);
|
||||
if (hasMoreComments.value) {
|
||||
return {
|
||||
discussion: {
|
||||
...previousDiscussion,
|
||||
lastComment: lastComment,
|
||||
comments: {
|
||||
elements: [
|
||||
...previousDiscussion.comments.elements.filter(
|
||||
({ id }: { id: string }) => id !== lastComment.id
|
||||
),
|
||||
lastComment,
|
||||
],
|
||||
total: previousDiscussion.comments.total + 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return previousDiscussion;
|
||||
},
|
||||
return previousDiscussion;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const discussion = computed(() => discussionResult.value?.discussion);
|
||||
@@ -272,7 +277,7 @@ const { mutate: replyToDiscussionMutation } = useMutation<{
|
||||
}>({
|
||||
query: GET_DISCUSSION,
|
||||
variables: {
|
||||
slug: props.slug,
|
||||
slug: slug.value,
|
||||
page: page.value,
|
||||
},
|
||||
});
|
||||
@@ -281,7 +286,7 @@ const { mutate: replyToDiscussionMutation } = useMutation<{
|
||||
|
||||
store.writeQuery({
|
||||
query: GET_DISCUSSION,
|
||||
variables: { slug: props.slug, page: page.value },
|
||||
variables: { slug: slug.value, page: page.value },
|
||||
data: {
|
||||
discussion: {
|
||||
...discussionCached,
|
||||
@@ -324,7 +329,7 @@ const { mutate: updateComment } = useMutation<
|
||||
}>({
|
||||
query: GET_DISCUSSION,
|
||||
variables: {
|
||||
slug: props.slug,
|
||||
slug: slug.value,
|
||||
page: page.value,
|
||||
},
|
||||
});
|
||||
@@ -339,7 +344,7 @@ const { mutate: updateComment } = useMutation<
|
||||
}
|
||||
store.writeQuery({
|
||||
query: GET_DISCUSSION,
|
||||
variables: { slug: props.slug, page: page.value },
|
||||
variables: { slug: slug.value, page: page.value },
|
||||
data: { discussion: discussionCached },
|
||||
});
|
||||
},
|
||||
@@ -379,7 +384,7 @@ const loadMoreComments = async (): Promise<void> => {
|
||||
await fetchMore({
|
||||
// New variables
|
||||
variables: {
|
||||
slug: props.slug,
|
||||
slug: slug.value,
|
||||
page: page.value,
|
||||
limit: COMMENTS_PER_PAGE,
|
||||
},
|
||||
|
||||
@@ -83,7 +83,7 @@ import EmptyContent from "@/components/Utils/EmptyContent.vue";
|
||||
import { usePersonStatusGroup } from "@/composition/apollo/actor";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRouteQuery, integerTransformer } from "vue-use-route-query";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed } from "vue";
|
||||
|
||||
const page = useRouteQuery("page", 1, integerTransformer);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ErrorCode } from "@/types/enums";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRouteQuery } from "vue-use-route-query";
|
||||
import { computed } from "vue";
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
import RouteName from "@/router/name";
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import EventConversations from "../../components/Conversations/EventConversations.vue";
|
||||
import NewPrivateMessage from "../../components/Participation/NewPrivateMessage.vue";
|
||||
import { useFetchEvent } from "@/composition/apollo/event";
|
||||
|
||||
21
src/views/Event/CalendarView.vue
Normal file
21
src/views/Event/CalendarView.vue
Normal file
@@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<div class="container mx-auto px-1 mb-6">
|
||||
<h1 v-if="!isMobile">
|
||||
{{ t("Calendar") }}
|
||||
</h1>
|
||||
|
||||
<div class="p-2">
|
||||
<EventsCalendar v-if="!isMobile" />
|
||||
<EventsAgenda v-else />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from "vue-i18n";
|
||||
import EventsAgenda from "@/components/FullCalendar/EventsAgenda.vue";
|
||||
import EventsCalendar from "@/components/FullCalendar/EventsCalendar.vue";
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
const isMobile = window.innerWidth < 760;
|
||||
</script>
|
||||
@@ -241,19 +241,36 @@
|
||||
{{ t('Page limited to my group (asks for auth)') }}
|
||||
</o-radio>
|
||||
</div>-->
|
||||
</section>
|
||||
<section class="my-4">
|
||||
<h2>
|
||||
{{ t("How to register") }}
|
||||
</h2>
|
||||
|
||||
<div class="field">
|
||||
<o-radio
|
||||
v-model="registerOption"
|
||||
name="registerOption"
|
||||
:native-value="RegisterOption.MOBILIZON"
|
||||
>{{ t("I want to manage the registration on Mobilizon") }}</o-radio
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<o-radio
|
||||
v-model="registerOption"
|
||||
name="registerOption"
|
||||
:native-value="RegisterOption.EXTERNAL"
|
||||
>{{
|
||||
t("I want to manage the registration with an external provider")
|
||||
}}</o-radio
|
||||
>
|
||||
</div>
|
||||
|
||||
<o-field
|
||||
:label="t('External registration')"
|
||||
v-if="features?.eventExternal"
|
||||
v-if="registerOption === RegisterOption.EXTERNAL"
|
||||
:label="t('URL')"
|
||||
>
|
||||
<o-switch v-model="externalParticipation">
|
||||
{{
|
||||
t("I want to manage the registration with an external provider")
|
||||
}}
|
||||
</o-switch>
|
||||
</o-field>
|
||||
|
||||
<o-field v-if="externalParticipation" :label="t('URL')">
|
||||
<o-input
|
||||
icon="link"
|
||||
type="url"
|
||||
@@ -264,7 +281,10 @@
|
||||
</o-field>
|
||||
|
||||
<o-field
|
||||
v-if="anonymousParticipationConfig?.allowed && !externalParticipation"
|
||||
v-if="
|
||||
anonymousParticipationConfig?.allowed &&
|
||||
registerOption === RegisterOption.MOBILIZON
|
||||
"
|
||||
:label="t('Anonymous participations')"
|
||||
>
|
||||
<o-switch v-model="eventOptions.anonymousParticipation">
|
||||
@@ -287,20 +307,35 @@
|
||||
|
||||
<o-field
|
||||
:label="t('Participation approval')"
|
||||
v-show="!externalParticipation"
|
||||
v-show="registerOption === RegisterOption.MOBILIZON"
|
||||
>
|
||||
<o-switch v-model="needsApproval">{{
|
||||
t("I want to approve every participation request")
|
||||
}}</o-switch>
|
||||
</o-field>
|
||||
|
||||
<o-field :label="t('Number of places')" v-show="!externalParticipation">
|
||||
<o-field
|
||||
:label="t('Showing participants')"
|
||||
v-show="registerOption === RegisterOption.MOBILIZON"
|
||||
>
|
||||
<o-switch v-model="hideParticipants">{{
|
||||
t("Hide the number of participants")
|
||||
}}</o-switch>
|
||||
</o-field>
|
||||
|
||||
<o-field
|
||||
:label="t('Number of places')"
|
||||
v-show="registerOption === RegisterOption.MOBILIZON"
|
||||
>
|
||||
<o-switch v-model="limitedPlaces">{{
|
||||
t("Limited number of places")
|
||||
}}</o-switch>
|
||||
</o-field>
|
||||
|
||||
<div class="" v-if="limitedPlaces && !externalParticipation">
|
||||
<div
|
||||
class=""
|
||||
v-if="limitedPlaces && registerOption === RegisterOption.MOBILIZON"
|
||||
>
|
||||
<o-field :label="t('Number of places')" label-for="number-of-places">
|
||||
<o-input
|
||||
type="number"
|
||||
@@ -635,7 +670,7 @@ import {
|
||||
import { useMutation } from "@vue/apollo-composable";
|
||||
import { Dialog } from "@/plugins/dialog";
|
||||
import { Notifier } from "@/plugins/notifier";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useOruga } from "@oruga-ui/oruga-next";
|
||||
import type { Locale } from "date-fns";
|
||||
import sortBy from "lodash/sortBy";
|
||||
@@ -1091,6 +1126,15 @@ const needsApproval = computed({
|
||||
},
|
||||
});
|
||||
|
||||
const hideParticipants = computed({
|
||||
get(): boolean {
|
||||
return event.value?.options.hideNumberOfParticipants;
|
||||
},
|
||||
set(value: boolean) {
|
||||
event.value.options.hideNumberOfParticipants = value;
|
||||
},
|
||||
});
|
||||
|
||||
const checkTitleLength = computed((): Array<string | undefined> => {
|
||||
return event.value.title.length > 80
|
||||
? ["info", t("The event title will be ellipsed.")]
|
||||
@@ -1359,12 +1403,19 @@ const orderedCategories = computed(() => {
|
||||
return sortBy(eventCategories.value, ["label"]);
|
||||
});
|
||||
|
||||
const externalParticipation = computed({
|
||||
const RegisterOption = {
|
||||
MOBILIZON: "mobilizon",
|
||||
EXTERNAL: "external",
|
||||
};
|
||||
|
||||
const registerOption = computed({
|
||||
get() {
|
||||
return event.value?.joinOptions === EventJoinOptions.EXTERNAL;
|
||||
return event.value?.joinOptions === EventJoinOptions.EXTERNAL
|
||||
? RegisterOption.EXTERNAL
|
||||
: RegisterOption.MOBILIZON;
|
||||
},
|
||||
set(newValue) {
|
||||
if (newValue === true) {
|
||||
if (newValue === RegisterOption.EXTERNAL) {
|
||||
event.value.joinOptions = EventJoinOptions.EXTERNAL;
|
||||
} else {
|
||||
event.value.joinOptions = EventJoinOptions.FREE;
|
||||
|
||||
@@ -18,6 +18,16 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="start-time-icon-wrapper relative"
|
||||
v-if="event?.beginsOn && event?.options.showStartTime"
|
||||
>
|
||||
<start-time-icon
|
||||
:date="event.beginsOn.toString()"
|
||||
class="absolute right-3 -top-16"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<section class="intro px-2 pt-4" dir="auto">
|
||||
<div class="flex flex-wrap gap-2 justify-end">
|
||||
<div class="flex-1 min-w-[300px]">
|
||||
@@ -289,6 +299,7 @@ import {
|
||||
usernameWithDomain,
|
||||
} from "@/types/actor";
|
||||
import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
|
||||
import StartTimeIcon from "@/components/Event/StartTimeIcon.vue";
|
||||
import SkeletonDateCalendarIcon from "@/components/Event/SkeletonDateCalendarIcon.vue";
|
||||
import Earth from "vue-material-design-icons/Earth.vue";
|
||||
import Link from "vue-material-design-icons/Link.vue";
|
||||
@@ -326,7 +337,7 @@ import {
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { Notifier } from "@/plugins/notifier";
|
||||
import { AbsintheGraphQLErrors } from "@/types/errors.model";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
|
||||
const IntegrationTwitch = defineAsyncComponent(
|
||||
() => import("@/components/Event/Integrations/TwitchIntegration.vue")
|
||||
|
||||
@@ -116,7 +116,7 @@ import {
|
||||
useRouteQuery,
|
||||
} from "vue-use-route-query";
|
||||
import { MemberRole } from "@/types/enums";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const EVENTS_PAGE_LIMIT = 10;
|
||||
|
||||
@@ -151,7 +151,6 @@
|
||||
true // !$apollo.loading
|
||||
"
|
||||
>
|
||||
<div class="img-container h-64 prose" />
|
||||
<div class="text-center prose dark:prose-invert max-w-full">
|
||||
<p>
|
||||
{{
|
||||
@@ -237,7 +236,7 @@ import {
|
||||
import { Locale } from "date-fns";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRestrictions } from "@/composition/apollo/config";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
|
||||
const EventParticipationCard = defineAsyncComponent(
|
||||
() => import("@/components/Event/EventParticipationCard.vue")
|
||||
@@ -500,24 +499,3 @@ useHead({
|
||||
title: computed(() => t("My events")),
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.not-found {
|
||||
.img-container {
|
||||
background-image: url("../../../img/pics/event_creation-480w.webp");
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
& {
|
||||
background-image: url("../../../img/pics/event_creation-1024w.webp");
|
||||
}
|
||||
}
|
||||
|
||||
max-width: 450px;
|
||||
height: 300px;
|
||||
box-shadow: 0 0 8px 8px white inset;
|
||||
background-size: cover;
|
||||
border-radius: 10px;
|
||||
margin: auto auto 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -284,7 +284,7 @@ import Incognito from "vue-material-design-icons/Incognito.vue";
|
||||
import EmptyContent from "@/components/Utils/EmptyContent.vue";
|
||||
import { Notifier } from "@/plugins/notifier";
|
||||
import Tag from "@/components/TagElement.vue";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
|
||||
const PARTICIPANTS_PER_PAGE = 10;
|
||||
const MESSAGE_ELLIPSIS_LENGTH = 130;
|
||||
|
||||
@@ -231,7 +231,7 @@ import {
|
||||
useHost,
|
||||
} from "@/composition/config";
|
||||
import { Notifier } from "@/plugins/notifier";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { Openness, GroupVisibility } from "@/types/enums";
|
||||
import FullAddressAutoComplete from "@/components/Event/FullAddressAutoComplete.vue";
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ import {
|
||||
useRouteQuery,
|
||||
} from "vue-use-route-query";
|
||||
import { computed, inject } from "vue";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { usePersonStatusGroup } from "@/composition/apollo/actor";
|
||||
import { MemberRole } from "@/types/enums";
|
||||
|
||||
@@ -250,7 +250,7 @@ import {
|
||||
} from "@/graphql/member";
|
||||
import { usernameWithDomain, displayName, IGroup } from "@/types/actor";
|
||||
import EmptyContent from "@/components/Utils/EmptyContent.vue";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { computed, inject, ref } from "vue";
|
||||
|
||||
@@ -208,7 +208,7 @@ import { DELETE_GROUP } from "@/graphql/group";
|
||||
import { useMutation } from "@vue/apollo-composable";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Dialog } from "@/plugins/dialog";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { Notifier } from "@/plugins/notifier";
|
||||
|
||||
const Editor = defineAsyncComponent(
|
||||
|
||||
@@ -706,7 +706,7 @@ import AccountMultiplePlus from "vue-material-design-icons/AccountMultiplePlus.v
|
||||
import Earth from "vue-material-design-icons/Earth.vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useCreateReport } from "@/composition/apollo/report";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import Discussions from "@/components/Group/Sections/DiscussionsSection.vue";
|
||||
import Resources from "@/components/Group/Sections/ResourcesSection.vue";
|
||||
import Posts from "@/components/Group/Sections/PostsSection.vue";
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
>
|
||||
<div class="">
|
||||
<div class="">
|
||||
<div class="img-container" />
|
||||
<div class="text-center prose dark:prose-invert max-w-full">
|
||||
<p>
|
||||
{{ t("You are not part of any group.") }}
|
||||
@@ -92,7 +91,7 @@ import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { IUser } from "@/types/current-user.model";
|
||||
import { integerTransformer, useRouteQuery } from "vue-use-route-query";
|
||||
import { computed, inject } from "vue";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Notifier } from "@/plugins/notifier";
|
||||
@@ -201,23 +200,4 @@ section {
|
||||
.group-member-card {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.not-found {
|
||||
.img-container {
|
||||
background-image: url("../../../img/pics/group-480w.webp");
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
& {
|
||||
background-image: url("../../../img/pics/group-1024w.webp");
|
||||
}
|
||||
}
|
||||
|
||||
max-width: 450px;
|
||||
height: 300px;
|
||||
box-shadow: 0 0 8px 8px white inset;
|
||||
background-size: cover;
|
||||
border-radius: 10px;
|
||||
margin: auto auto 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import RouteName from "@/router/name";
|
||||
import SettingMenuSection from "@/components/Settings/SettingMenuSection.vue";
|
||||
import SettingMenuItem from "@/components/Settings/SettingMenuItem.vue";
|
||||
|
||||
@@ -166,7 +166,7 @@ import SkeletonActivityItem from "../../components/Activity/SkeletonActivityItem
|
||||
import RouteName from "../../router/name";
|
||||
import TimelineText from "vue-material-design-icons/TimelineText.vue";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { enumTransformer, useRouteQuery } from "vue-use-route-query";
|
||||
import { computed, defineAsyncComponent, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
@@ -144,41 +144,6 @@
|
||||
<CloseGroups :userLocation="userLocation" @doGeoLoc="performGeoLocation()" />
|
||||
<OnlineEvents />
|
||||
<LastEvents v-if="instanceName" :instanceName="instanceName" />
|
||||
<!-- Unlogged content section -->
|
||||
<picture v-if="!currentUser?.isLoggedIn">
|
||||
<source
|
||||
media="(max-width: 799px)"
|
||||
:srcset="`/img/pics/homepage-480w.webp`"
|
||||
type="image/webp"
|
||||
/>
|
||||
|
||||
<source
|
||||
media="(max-width: 1024px)"
|
||||
:srcset="`/img/pics/homepage-1024w.webp`"
|
||||
type="image/webp"
|
||||
/>
|
||||
|
||||
<source
|
||||
media="(max-width: 1920px)"
|
||||
:srcset="`/img/pics/homepage-1920w.webp`"
|
||||
type="image/webp"
|
||||
/>
|
||||
|
||||
<source
|
||||
media="(min-width: 1921px)"
|
||||
:srcset="`/img/pics/homepage.webp`"
|
||||
type="image/webp"
|
||||
/>
|
||||
|
||||
<img
|
||||
:src="`/img/pics/homepage-1024w.webp`"
|
||||
width="3840"
|
||||
height="2719"
|
||||
alt=""
|
||||
loading="lazy"
|
||||
/>
|
||||
</picture>
|
||||
<presentation v-if="!currentUser?.isLoggedIn" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@@ -214,7 +179,6 @@ import {
|
||||
UPDATE_CURRENT_USER_LOCATION_CLIENT,
|
||||
} from "@/graphql/location";
|
||||
import { LocationType } from "@/types/user-location.model";
|
||||
import Presentation from "@/components/Home/MobilizonPresentation.vue";
|
||||
import CategoriesPreview from "@/components/Home/CategoriesPreview.vue";
|
||||
import UnloggedIntroduction from "@/components/Home/UnloggedIntroduction.vue";
|
||||
import SearchFields from "@/components/Home/SearchFields.vue";
|
||||
|
||||
@@ -38,7 +38,7 @@ import { computed, reactive } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRouteQuery } from "vue-use-route-query";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
|
||||
const router = useRouter();
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
@@ -442,7 +442,7 @@ import { displayNameAndUsername, displayName } from "../../types/actor";
|
||||
import { Paginate } from "@/types/paginate";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { integerTransformer, useRouteQuery } from "vue-use-route-query";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { formatDateTimeString } from "@/filters/datetime";
|
||||
|
||||
@@ -95,7 +95,7 @@ import { Paginate } from "@/types/paginate";
|
||||
import debounce from "lodash/debounce";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed } from "vue";
|
||||
import {
|
||||
enumTransformer,
|
||||
|
||||
@@ -414,7 +414,7 @@ import { GraphQLError } from "graphql";
|
||||
import { ApolloCache, FetchResult } from "@apollo/client/core";
|
||||
import { useLazyQuery, useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { useCurrentActorClient } from "@/composition/apollo/actor";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRouter } from "vue-router";
|
||||
import { ref, computed, inject } from "vue";
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRouteQuery } from "vue-use-route-query";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { DEVICE_ACTIVATION } from "@/graphql/application";
|
||||
import { useMutation } from "@vue/apollo-composable";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed, reactive, ref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import AuthorizeApplication from "@/components/OAuth/AuthorizeApplication.vue";
|
||||
|
||||
@@ -2,20 +2,6 @@
|
||||
<section class="container mx-auto py-4 is-max-desktop max-w-2xl">
|
||||
<div class="">
|
||||
<div class="">
|
||||
<picture>
|
||||
<source
|
||||
:srcset="`/img/pics/error-480w.webp 1x, /img/pics/error-1024w.webp 2x`"
|
||||
type="image/webp"
|
||||
/>
|
||||
|
||||
<img
|
||||
:src="`/img/pics/error-480w.webp`"
|
||||
alt=""
|
||||
width="2616"
|
||||
height="1698"
|
||||
loading="lazy"
|
||||
/>
|
||||
</picture>
|
||||
<h1 class="text-4xl mb-3">
|
||||
{{ $t("The page you're looking for doesn't exist.") }}
|
||||
</h1>
|
||||
@@ -55,7 +41,7 @@
|
||||
</section>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
@@ -154,7 +154,7 @@ import {
|
||||
useCurrentActorClient,
|
||||
usePersonStatusGroup,
|
||||
} from "@/composition/apollo/actor";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { computed, inject, onMounted, ref, watch } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
@@ -83,7 +83,7 @@ import MultiPostListItem from "../../components/Post/MultiPostListItem.vue";
|
||||
import { useCurrentActorClient } from "@/composition/apollo/actor";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { computed } from "vue";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { integerTransformer, useRouteQuery } from "vue-use-route-query";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { MemberRole } from "@/types/enums";
|
||||
|
||||
@@ -268,7 +268,7 @@ import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { computed, inject, ref } from "vue";
|
||||
import { IPost } from "@/types/post.model";
|
||||
import { DELETE_POST, FETCH_POST } from "@/graphql/post";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { formatDateTimeString } from "@/filters/datetime";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useCreateReport } from "@/composition/apollo/report";
|
||||
|
||||
@@ -245,7 +245,7 @@ import { computed, nextTick, reactive, ref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { integerTransformer, useRouteQuery } from "vue-use-route-query";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useResourceProviders } from "@/composition/apollo/config";
|
||||
import Folder from "vue-material-design-icons/Folder.vue";
|
||||
import Link from "vue-material-design-icons/Link.vue";
|
||||
|
||||
@@ -45,6 +45,16 @@
|
||||
:size="24"
|
||||
/>
|
||||
|
||||
<Calendar
|
||||
v-if="content.contentType === ContentType.SHORTEVENTS"
|
||||
:size="24"
|
||||
/>
|
||||
|
||||
<CalendarStar
|
||||
v-if="content.contentType === ContentType.LONGEVENTS"
|
||||
:size="24"
|
||||
/>
|
||||
|
||||
<AccountMultiple
|
||||
v-if="content.contentType === ContentType.GROUPS"
|
||||
:size="24"
|
||||
@@ -443,8 +453,15 @@
|
||||
class="hidden sm:flex items-center justify-between dark:text-slate-100 mb-2"
|
||||
>
|
||||
<p v-if="totalCount === 0">
|
||||
<span v-if="contentType === ContentType.EVENTS">{{
|
||||
t("No events found")
|
||||
<span
|
||||
v-if="
|
||||
contentType === ContentType.EVENTS ||
|
||||
contentType === ContentType.SHORTEVENTS
|
||||
"
|
||||
>{{ t("No events found") }}</span
|
||||
>
|
||||
<span v-else-if="contentType === ContentType.LONGEVENTS">{{
|
||||
t("No activities found")
|
||||
}}</span>
|
||||
<span v-else-if="contentType === ContentType.GROUPS">{{
|
||||
t("No groups found")
|
||||
@@ -452,7 +469,12 @@
|
||||
<span v-else>{{ t("No results found") }}</span>
|
||||
</p>
|
||||
<p v-else>
|
||||
<span v-if="contentType === 'EVENTS'">
|
||||
<span
|
||||
v-if="
|
||||
contentType === ContentType.EVENTS ||
|
||||
contentType === ContentType.SHORTEVENTS
|
||||
"
|
||||
>
|
||||
{{
|
||||
t(
|
||||
"{eventsCount} events found",
|
||||
@@ -461,7 +483,16 @@
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
<span v-else-if="contentType === 'GROUPS'">
|
||||
<span v-else-if="contentType === ContentType.LONGEVENTS">
|
||||
{{
|
||||
t(
|
||||
"{eventsCount} activities found",
|
||||
{ eventsCount: searchEvents?.total },
|
||||
searchEvents?.total ?? 0
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
<span v-else-if="contentType === ContentType.GROUPS">
|
||||
{{
|
||||
t(
|
||||
"{groupsCount} groups found",
|
||||
@@ -597,7 +628,13 @@
|
||||
:aria-current-label="t('Current page')"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="contentType === ContentType.EVENTS">
|
||||
<template
|
||||
v-else-if="
|
||||
contentType === ContentType.EVENTS ||
|
||||
contentType === ContentType.SHORTEVENTS ||
|
||||
contentType === ContentType.LONGEVENTS
|
||||
"
|
||||
>
|
||||
<template v-if="searchLoading">
|
||||
<SkeletonEventResultList v-for="i in 8" :key="i" />
|
||||
</template>
|
||||
@@ -625,13 +662,23 @@
|
||||
>
|
||||
</o-pagination>
|
||||
</template>
|
||||
<EmptyContent v-else-if="searchLoading === false" icon="calendar">
|
||||
<EmptyContent
|
||||
v-else-if="searchLoading === false"
|
||||
:icon="
|
||||
contentType === ContentType.LONGEVENTS
|
||||
? 'calendar-star'
|
||||
: 'calendar'
|
||||
"
|
||||
>
|
||||
<span v-if="searchIsUrl">
|
||||
{{ t("No event found at this address") }}
|
||||
</span>
|
||||
<span v-else-if="!search">
|
||||
<span v-else-if="!search && contentType !== ContentType.LONGEVENTS">
|
||||
{{ t("No events found") }}
|
||||
</span>
|
||||
<span v-else-if="!search && contentType === ContentType.LONGEVENTS">
|
||||
{{ t("No activities found") }}
|
||||
</span>
|
||||
<i18n-t keypath="No events found for {search}" tag="span" v-else>
|
||||
<template #search>
|
||||
<b>{{ search }}</b>
|
||||
@@ -694,7 +741,7 @@
|
||||
icon="account-multiple"
|
||||
>
|
||||
<span v-if="!search">
|
||||
{{ t("No events found") }}
|
||||
{{ t("No groups found") }}
|
||||
</span>
|
||||
<i18n-t keypath="No groups found for {search}" tag="span" v-else>
|
||||
<template #search>
|
||||
@@ -767,10 +814,11 @@ import {
|
||||
booleanTransformer,
|
||||
} from "vue-use-route-query";
|
||||
import Calendar from "vue-material-design-icons/Calendar.vue";
|
||||
import CalendarStar from "vue-material-design-icons/CalendarStar.vue";
|
||||
import AccountMultiple from "vue-material-design-icons/AccountMultiple.vue";
|
||||
import Magnify from "vue-material-design-icons/Magnify.vue";
|
||||
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import type { Locale } from "date-fns";
|
||||
import FilterSection from "@/components/Search/filters/FilterSection.vue";
|
||||
import { listShortDisjunctionFormatter } from "@/utils/listFormat";
|
||||
@@ -778,6 +826,7 @@ import langs from "@/i18n/langs.json";
|
||||
import {
|
||||
useEventCategories,
|
||||
useFeatures,
|
||||
useIsLongEvents,
|
||||
useSearchConfig,
|
||||
} from "@/composition/apollo/config";
|
||||
import { coordsToGeoHash } from "@/utils/location";
|
||||
@@ -892,7 +941,7 @@ const searchTarget = useRouteQuery(
|
||||
const mode = useRouteQuery("mode", ViewMode.LIST, enumTransformer(ViewMode));
|
||||
const sortBy = useRouteQuery(
|
||||
"sortBy",
|
||||
SortValues.MATCH_DESC,
|
||||
SortValues.START_TIME_ASC,
|
||||
enumTransformer(SortValues)
|
||||
);
|
||||
const bbox = useRouteQuery("bbox", undefined);
|
||||
@@ -904,6 +953,7 @@ const GROUP_PAGE_LIMIT = 16;
|
||||
|
||||
const { features } = useFeatures();
|
||||
const { eventCategories } = useEventCategories();
|
||||
const { islongEvents } = useIsLongEvents();
|
||||
|
||||
const orderedCategories = computed(() => {
|
||||
if (!eventCategories.value) return [];
|
||||
@@ -1017,20 +1067,41 @@ const searchIsUrl = computed((): boolean => {
|
||||
});
|
||||
|
||||
const contentTypeMapping = computed(() => {
|
||||
return [
|
||||
{
|
||||
contentType: "ALL",
|
||||
label: t("Everything"),
|
||||
},
|
||||
{
|
||||
contentType: "EVENTS",
|
||||
label: t("Events"),
|
||||
},
|
||||
{
|
||||
contentType: "GROUPS",
|
||||
label: t("Groups"),
|
||||
},
|
||||
];
|
||||
if (islongEvents.value) {
|
||||
return [
|
||||
{
|
||||
contentType: "ALL",
|
||||
label: t("Everything"),
|
||||
},
|
||||
{
|
||||
contentType: "SHORTEVENTS",
|
||||
label: t("Events"),
|
||||
},
|
||||
{
|
||||
contentType: "LONGEVENTS",
|
||||
label: t("Activities"),
|
||||
},
|
||||
{
|
||||
contentType: "GROUPS",
|
||||
label: t("Groups"),
|
||||
},
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
{
|
||||
contentType: "ALL",
|
||||
label: t("Everything"),
|
||||
},
|
||||
{
|
||||
contentType: "EVENTS",
|
||||
label: t("Events"),
|
||||
},
|
||||
{
|
||||
contentType: "GROUPS",
|
||||
label: t("Groups"),
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
const eventDistance = computed(() => {
|
||||
@@ -1138,6 +1209,16 @@ const geoHashLocation = computed(() =>
|
||||
|
||||
const radius = computed(() => Number.parseInt(distance.value.slice(0, -3)));
|
||||
|
||||
const longEvents = computed(() => {
|
||||
if (contentType.value === ContentType.SHORTEVENTS) {
|
||||
return false;
|
||||
} else if (contentType.value === ContentType.LONGEVENTS) {
|
||||
return true;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
const totalCount = computed(() => {
|
||||
return (searchEvents.value?.total ?? 0) + (searchGroups.value?.total ?? 0);
|
||||
});
|
||||
@@ -1150,7 +1231,11 @@ const sortOptions = computed(() => {
|
||||
},
|
||||
];
|
||||
|
||||
if (contentType.value == ContentType.EVENTS) {
|
||||
if (
|
||||
contentType.value === ContentType.EVENTS ||
|
||||
contentType.value === ContentType.SHORTEVENTS ||
|
||||
contentType.value === ContentType.LONGEVENTS
|
||||
) {
|
||||
options.push(
|
||||
{
|
||||
key: SortValues.START_TIME_ASC,
|
||||
@@ -1171,7 +1256,7 @@ const sortOptions = computed(() => {
|
||||
);
|
||||
}
|
||||
|
||||
if (contentType.value == ContentType.GROUPS) {
|
||||
if (contentType.value === ContentType.GROUPS) {
|
||||
options.push({
|
||||
key: SortValues.MEMBER_COUNT_DESC,
|
||||
label: t("Number of members"),
|
||||
@@ -1282,6 +1367,12 @@ watch(
|
||||
case ContentType.EVENTS:
|
||||
eventPage.value = 1;
|
||||
break;
|
||||
case ContentType.SHORTEVENTS:
|
||||
eventPage.value = 1;
|
||||
break;
|
||||
case ContentType.LONGEVENTS:
|
||||
eventPage.value = 1;
|
||||
break;
|
||||
case ContentType.GROUPS:
|
||||
groupPage.value = 1;
|
||||
break;
|
||||
@@ -1298,6 +1389,7 @@ const { result: searchElementsResult, loading: searchLoading } = useQuery<{
|
||||
location: geoHashLocation.value,
|
||||
beginsOn: start.value,
|
||||
endsOn: end.value,
|
||||
longevents: longEvents.value,
|
||||
radius: geoHashLocation.value ? radius.value : undefined,
|
||||
eventPage:
|
||||
contentType.value === ContentType.ALL ? page.value : eventPage.value,
|
||||
|
||||
@@ -235,7 +235,7 @@ import { useLoggedUser } from "@/composition/apollo/user";
|
||||
import { Notifier } from "@/plugins/notifier";
|
||||
import { IAuthProvider } from "@/types/enums";
|
||||
import { useMutation } from "@vue/apollo-composable";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { GraphQLError } from "graphql/error/GraphQLError";
|
||||
import { computed, inject, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
@@ -82,7 +82,7 @@ import {
|
||||
REVOKED_AUTHORIZED_APPLICATION,
|
||||
} from "@/graphql/application";
|
||||
import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed, inject } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import RouteName from "../../router/name";
|
||||
|
||||
@@ -339,7 +339,7 @@ import {
|
||||
} from "vue";
|
||||
import { IConfig } from "@/types/config.model";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { Dialog } from "@/plugins/dialog";
|
||||
|
||||
type NotificationSubType = { label: string; id: string };
|
||||
|
||||
@@ -148,7 +148,7 @@ import { AddressSearchType } from "@/types/enums";
|
||||
import { Address, IAddress } from "@/types/address.model";
|
||||
import { useTimezones } from "@/composition/apollo/config";
|
||||
import { useUserSettings, updateLocale } from "@/composition/apollo/user";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed, defineAsyncComponent, ref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useMutation } from "@vue/apollo-composable";
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
import SettingsMenu from "../components/Settings/SettingsMenu.vue";
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ import RouteName from "../../router/name";
|
||||
import { ApolloCache, FetchResult, InMemoryCache } from "@apollo/client/core";
|
||||
import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { useCurrentActorClient } from "@/composition/apollo/actor";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed, ref } from "vue";
|
||||
|
||||
const props = defineProps<{ id: string }>();
|
||||
|
||||
@@ -70,7 +70,7 @@ import { ITodoList } from "@/types/todolist";
|
||||
import RouteName from "../../router/name";
|
||||
import { useGroup } from "@/composition/apollo/group";
|
||||
import { computed, reactive } from "vue";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useMutation } from "@vue/apollo-composable";
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ import FullTodo from "@/components/Todo/FullTodo.vue";
|
||||
import RouteName from "../../router/name";
|
||||
import { displayName, usernameWithDomain } from "@/types/actor";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = defineProps<{ todoId: string }>();
|
||||
|
||||
@@ -143,7 +143,7 @@ import AuthProviders from "@/components/User/AuthProviders.vue";
|
||||
import RouteName from "@/router/name";
|
||||
import { LoginError, LoginErrorCode } from "@/types/enums";
|
||||
import { useCurrentUserClient } from "@/composition/apollo/user";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { enumTransformer, useRouteQuery } from "vue-use-route-query";
|
||||
import { useLazyCurrentUserIdentities } from "@/composition/apollo/actor";
|
||||
|
||||
@@ -245,8 +245,17 @@ const { onDone: onCurrentUserMutationDone, mutate: updateCurrentUserMutation } =
|
||||
|
||||
onCurrentUserMutationDone(async () => {
|
||||
console.debug("Current user mutation done, now setuping actors…");
|
||||
// since we fail to refresh the navbar properly, we force a page reload.
|
||||
// see the explanation of the bug bellow
|
||||
window.location = redirect.value || "/";
|
||||
try {
|
||||
/* FIXME this promise never resolved the first time
|
||||
no idea why !
|
||||
this appends even with the last version of apollo-composable (4.0.2)
|
||||
may be related to that : https://github.com/vuejs/apollo/issues/1543
|
||||
*/
|
||||
const result = await loadIdentities();
|
||||
console.debug("login, loadIdentities resolved");
|
||||
if (!result) return;
|
||||
await initializeCurrentActor(result.loggedUser.actors);
|
||||
} catch (err: any) {
|
||||
|
||||
@@ -48,7 +48,7 @@ import RouteName from "@/router/name";
|
||||
import { reactive, ref, computed } from "vue";
|
||||
import { useMutation } from "@vue/apollo-composable";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const props = defineProps<{ token: string }>();
|
||||
|
||||
@@ -12,7 +12,7 @@ import { ICurrentUser, IUser } from "../../types/current-user.model";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useLazyQuery, useMutation } from "@vue/apollo-composable";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed, onMounted } from "vue";
|
||||
import { getValueFromMeta } from "@/utils/html";
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ import { computed, reactive, ref, watch } from "vue";
|
||||
import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { AbsintheGraphQLErrors } from "@/types/errors.model";
|
||||
|
||||
type errorType = "danger" | "warning";
|
||||
|
||||
@@ -54,7 +54,7 @@ import RouteName from "@/router/name";
|
||||
import { ref, computed } from "vue";
|
||||
import { useMutation } from "@vue/apollo-composable";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
useHead({
|
||||
|
||||
@@ -63,7 +63,7 @@ import { SEND_RESET_PASSWORD } from "../../graphql/auth";
|
||||
import RouteName from "../../router/name";
|
||||
import { computed, ref } from "vue";
|
||||
import { useMutation } from "@vue/apollo-composable";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
import { USER_SETTINGS } from "@/graphql/user";
|
||||
import { IUser } from "@/types/current-user.model";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { computed, defineAsyncComponent, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import RouteName from "@/router/name";
|
||||
|
||||
@@ -31,7 +31,7 @@ import { ref, onBeforeMount, computed } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useMutation } from "@vue/apollo-composable";
|
||||
import { IUser } from "@/types/current-user.model";
|
||||
import { useHead } from "@unhead/vue";
|
||||
import { useHead } from "@/utils/head";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
Reference in New Issue
Block a user