@@ -1,3 +1,4 @@
|
||||
import { useI18n } from "vue-i18n";
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
@@ -22,7 +23,7 @@
|
||||
<p class="">{{ currentIdentity.name }}</p>
|
||||
<p class="">
|
||||
{{ `@${currentIdentity.preferredUsername}` }}
|
||||
<span v-if="masked">{{ $t("(Masked)") }}</span>
|
||||
<span v-if="masked">{{ t("(Masked)") }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="" v-else>
|
||||
@@ -33,7 +34,7 @@
|
||||
v-if="identities && identities.length > 1"
|
||||
@click="activateModal"
|
||||
>
|
||||
{{ $t("Change") }}
|
||||
{{ t("Change") }}
|
||||
</o-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -55,7 +56,7 @@
|
||||
</span>
|
||||
<o-modal
|
||||
v-model:active="isComponentModalActive"
|
||||
:close-button-aria-label="$t('Close')"
|
||||
:close-button-aria-label="t('Close')"
|
||||
>
|
||||
<identity-picker v-if="currentIdentity" v-model="currentIdentity" />
|
||||
</o-modal>
|
||||
@@ -67,6 +68,7 @@ import { computed, ref } from "vue";
|
||||
import { IPerson } from "../../types/actor";
|
||||
import IdentityPicker from "./IdentityPicker.vue";
|
||||
import AccountCircle from "vue-material-design-icons/AccountCircle.vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { identities } = useCurrentUserIdentities();
|
||||
|
||||
@@ -84,6 +86,8 @@ const props = withDefaults(
|
||||
|
||||
const emit = defineEmits(["update:modelValue"]);
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
const isComponentModalActive = ref(false);
|
||||
|
||||
const currentIdentity = computed({
|
||||
|
||||
@@ -230,8 +230,4 @@ p.description {
|
||||
margin-bottom: 15px;
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
section.section {
|
||||
background: $white;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -208,14 +208,13 @@ import {
|
||||
PERSON_FRAGMENT,
|
||||
PERSON_FRAGMENT_FEED_TOKENS,
|
||||
UPDATE_PERSON,
|
||||
} from "../../../graphql/actor";
|
||||
import { IPerson, displayName } from "../../../types/actor";
|
||||
import PictureUpload from "../../../components/PictureUpload.vue";
|
||||
import { MOBILIZON_INSTANCE_HOST } from "../../../api/_entrypoint";
|
||||
import RouteName from "../../../router/name";
|
||||
import { buildFileVariable } from "../../../utils/image";
|
||||
import { changeIdentity } from "../../../utils/identity";
|
||||
// import identityEditionMixin from "../../../mixins/identityEdition";
|
||||
} from "@/graphql/actor";
|
||||
import { IPerson, displayName } from "@/types/actor";
|
||||
import PictureUpload from "@/components/PictureUpload.vue";
|
||||
import { MOBILIZON_INSTANCE_HOST } from "@/api/_entrypoint";
|
||||
import RouteName from "@/router/name";
|
||||
import { buildFileVariable } from "@/utils/image";
|
||||
import { changeIdentity } from "@/utils/identity";
|
||||
import {
|
||||
CREATE_FEED_TOKEN_ACTOR,
|
||||
DELETE_FEED_TOKEN,
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<breadcrumbs-nav
|
||||
:links="[
|
||||
{ name: RouteName.ADMIN, text: $t('Admin') },
|
||||
{ text: $t('Dashboard') },
|
||||
]"
|
||||
/>
|
||||
<section>
|
||||
<h1>{{ $t("Administration") }}</h1>
|
||||
<div class="tile is-ancestor" v-if="dashboard">
|
||||
<div class="tile is-vertical">
|
||||
<div class="tile">
|
||||
<div class="tile is-parent is-vertical is-6">
|
||||
<article class="tile is-child box">
|
||||
<p class="dashboard-number">{{ dashboard.numberOfEvents }}</p>
|
||||
<i18n-t
|
||||
keypath="Published events with {comments} comments and {participations} confirmed participations"
|
||||
tag="p"
|
||||
>
|
||||
<template #comments>
|
||||
<b>{{ dashboard.numberOfComments }}</b>
|
||||
</template>
|
||||
<template #participations>
|
||||
<b>{{
|
||||
dashboard.numberOfConfirmedParticipationsToLocalEvents
|
||||
}}</b>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</article>
|
||||
<article class="tile is-child box">
|
||||
<router-link :to="{ name: RouteName.ADMIN_GROUPS }">
|
||||
<p class="dashboard-number">{{ dashboard.numberOfGroups }}</p>
|
||||
<p>{{ $t("Groups") }}</p>
|
||||
</router-link>
|
||||
</article>
|
||||
</div>
|
||||
<div class="tile is-parent is-vertical">
|
||||
<article class="tile is-child box">
|
||||
<router-link :to="{ name: RouteName.USERS }">
|
||||
<p class="dashboard-number">{{ dashboard.numberOfUsers }}</p>
|
||||
<p>{{ $t("Users") }}</p>
|
||||
</router-link>
|
||||
</article>
|
||||
<article class="tile is-child box">
|
||||
<router-link :to="{ name: RouteName.RELAY_FOLLOWERS }">
|
||||
<p class="dashboard-number">
|
||||
{{ dashboard.numberOfFollowers }}
|
||||
</p>
|
||||
<p>{{ $t("Instances following you") }}</p>
|
||||
</router-link>
|
||||
</article>
|
||||
</div>
|
||||
<div class="tile is-parent is-vertical">
|
||||
<article class="tile is-child box">
|
||||
<router-link :to="{ name: RouteName.REPORTS }">
|
||||
<p class="dashboard-number">
|
||||
{{ dashboard.numberOfReports }}
|
||||
</p>
|
||||
<p>{{ $t("Opened reports") }}</p>
|
||||
</router-link>
|
||||
</article>
|
||||
<article class="tile is-child box">
|
||||
<router-link :to="{ name: RouteName.RELAY_FOLLOWINGS }">
|
||||
<p class="dashboard-number">
|
||||
{{ dashboard.numberOfFollowings }}
|
||||
</p>
|
||||
<p>{{ $t("Instances you follow") }}</p>
|
||||
</router-link>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile">
|
||||
<div
|
||||
class="tile is-parent is-vertical is-6"
|
||||
v-if="dashboard.lastPublicEventPublished"
|
||||
>
|
||||
<article class="tile is-child box">
|
||||
<router-link
|
||||
:to="{
|
||||
name: RouteName.EVENT,
|
||||
params: { uuid: dashboard.lastPublicEventPublished.uuid },
|
||||
}"
|
||||
>
|
||||
<p>{{ $t("Last published event") }}</p>
|
||||
<p class="subtitle">
|
||||
{{ dashboard.lastPublicEventPublished.title }}
|
||||
</p>
|
||||
<figure
|
||||
class="image is-4by3"
|
||||
v-if="dashboard.lastPublicEventPublished.picture"
|
||||
>
|
||||
<img
|
||||
:src="dashboard.lastPublicEventPublished.picture.url"
|
||||
/>
|
||||
</figure>
|
||||
</router-link>
|
||||
</article>
|
||||
</div>
|
||||
<div
|
||||
class="tile is-parent is-vertical"
|
||||
v-if="dashboard.lastGroupCreated"
|
||||
>
|
||||
<article class="tile is-child box">
|
||||
<router-link
|
||||
:to="{
|
||||
name: RouteName.GROUP,
|
||||
params: {
|
||||
preferredUsername: usernameWithDomain(
|
||||
dashboard.lastGroupCreated
|
||||
),
|
||||
},
|
||||
}"
|
||||
>
|
||||
<p>{{ $t("Last group created") }}</p>
|
||||
<p class="subtitle">
|
||||
{{
|
||||
dashboard.lastGroupCreated.name ||
|
||||
dashboard.lastGroupCreated.preferredUsername
|
||||
}}
|
||||
</p>
|
||||
<figure
|
||||
class="image is-4by3"
|
||||
v-if="dashboard.lastGroupCreated.avatar"
|
||||
>
|
||||
<img :src="dashboard.lastGroupCreated.avatar.url" />
|
||||
</figure>
|
||||
</router-link>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { DASHBOARD } from "@/graphql/admin";
|
||||
import { IDashboard } from "@/types/admin.model";
|
||||
import { usernameWithDomain } from "@/types/actor";
|
||||
import RouteName from "@/router/name";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@vueuse/head";
|
||||
|
||||
const { result: dashboardResult } = useQuery<{ dashboard: IDashboard }>(
|
||||
DASHBOARD
|
||||
);
|
||||
|
||||
const dashboard = computed(() => dashboardResult.value?.dashboard);
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
useHead({
|
||||
title: computed(() => t("Administration")),
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dashboard-number {
|
||||
font-size: 40px;
|
||||
font-weight: 700;
|
||||
line-height: 1.125;
|
||||
}
|
||||
|
||||
.tile a,
|
||||
article.tile a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.image.is-4by3 img {
|
||||
object-fit: cover;
|
||||
}
|
||||
</style>
|
||||
151
js/src/views/Admin/DashboardView.vue
Normal file
151
js/src/views/Admin/DashboardView.vue
Normal file
@@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<div>
|
||||
<breadcrumbs-nav
|
||||
:links="[
|
||||
{ name: RouteName.ADMIN, text: t('Admin') },
|
||||
{ text: t('Dashboard') },
|
||||
]"
|
||||
/>
|
||||
<section>
|
||||
<h1>{{ t("Administration") }}</h1>
|
||||
<div
|
||||
class="grid grid-cols-1 lg:grid-rows-2 lg:grid-flow-col gap-x-4 items-stretch"
|
||||
>
|
||||
<NumberDashboardTile :number="dashboard?.numberOfEvents">
|
||||
<template #subtitle>
|
||||
<i18n-t
|
||||
keypath="Published events with {comments} comments and {participations} confirmed participations"
|
||||
tag="p"
|
||||
>
|
||||
<template #comments>
|
||||
<b>{{ dashboard?.numberOfComments }}</b>
|
||||
</template>
|
||||
<template #participations>
|
||||
<b>{{
|
||||
dashboard?.numberOfConfirmedParticipationsToLocalEvents
|
||||
}}</b>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</template>
|
||||
</NumberDashboardTile>
|
||||
<LinkedNumberDashboardTile
|
||||
:number="dashboard?.numberOfGroups"
|
||||
:subtitle="t('Groups', dashboard?.numberOfGroups ?? 0)"
|
||||
:to="{ name: RouteName.ADMIN_GROUPS }"
|
||||
/>
|
||||
<LinkedNumberDashboardTile
|
||||
:number="dashboard?.numberOfUsers"
|
||||
:subtitle="t('Users', dashboard?.numberOfUsers ?? 0)"
|
||||
:to="{ name: RouteName.ADMIN_GROUPS }"
|
||||
/>
|
||||
<LinkedNumberDashboardTile
|
||||
:number="dashboard?.numberOfReports"
|
||||
:subtitle="t('Opened reports', dashboard?.numberOfReports ?? 0)"
|
||||
:to="{ name: RouteName.REPORTS }"
|
||||
/>
|
||||
<LinkedNumberDashboardTile
|
||||
:number="dashboard?.numberOfFollowers"
|
||||
:subtitle="
|
||||
t('Instances following you', dashboard?.numberOfFollowers ?? 0)
|
||||
"
|
||||
:to="{
|
||||
name: RouteName.INSTANCES,
|
||||
query: { followStatus: InstanceFilterFollowStatus.FOLLOWING },
|
||||
}"
|
||||
/>
|
||||
<LinkedNumberDashboardTile
|
||||
:number="dashboard?.numberOfFollowings"
|
||||
:subtitle="
|
||||
t('Instances you follow', dashboard?.numberOfFollowings ?? 0)
|
||||
"
|
||||
:to="{
|
||||
name: RouteName.INSTANCES,
|
||||
query: { followStatus: InstanceFilterFollowStatus.FOLLOWED },
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
<div class="tile">
|
||||
<div
|
||||
class="tile is-parent is-vertical is-6"
|
||||
v-if="dashboard?.lastPublicEventPublished"
|
||||
>
|
||||
<article class="tile is-child box">
|
||||
<router-link
|
||||
:to="{
|
||||
name: RouteName.EVENT,
|
||||
params: { uuid: dashboard?.lastPublicEventPublished.uuid },
|
||||
}"
|
||||
>
|
||||
<p>{{ t("Last published event") }}</p>
|
||||
<p>
|
||||
{{ dashboard?.lastPublicEventPublished.title }}
|
||||
</p>
|
||||
<figure
|
||||
class="image is-4by3"
|
||||
v-if="dashboard?.lastPublicEventPublished.picture"
|
||||
>
|
||||
<img :src="dashboard?.lastPublicEventPublished.picture.url" />
|
||||
</figure>
|
||||
</router-link>
|
||||
</article>
|
||||
</div>
|
||||
<div
|
||||
class="tile is-parent is-vertical"
|
||||
v-if="dashboard?.lastGroupCreated"
|
||||
>
|
||||
<article class="tile is-child box">
|
||||
<router-link
|
||||
:to="{
|
||||
name: RouteName.GROUP,
|
||||
params: {
|
||||
preferredUsername: usernameWithDomain(
|
||||
dashboard?.lastGroupCreated
|
||||
),
|
||||
},
|
||||
}"
|
||||
>
|
||||
<p>{{ t("Last group created") }}</p>
|
||||
<p>
|
||||
{{
|
||||
dashboard?.lastGroupCreated.name ||
|
||||
dashboard?.lastGroupCreated.preferredUsername
|
||||
}}
|
||||
</p>
|
||||
<figure
|
||||
class="image is-4by3"
|
||||
v-if="dashboard?.lastGroupCreated.avatar"
|
||||
>
|
||||
<img :src="dashboard?.lastGroupCreated.avatar.url" />
|
||||
</figure>
|
||||
</router-link>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { DASHBOARD } from "@/graphql/admin";
|
||||
import { IDashboard } from "@/types/admin.model";
|
||||
import { usernameWithDomain } from "@/types/actor";
|
||||
import RouteName from "@/router/name";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@vueuse/head";
|
||||
import NumberDashboardTile from "@/components/Dashboard/NumberDashboardTile.vue";
|
||||
import LinkedNumberDashboardTile from "@/components/Dashboard/LinkedNumberDashboardTile.vue";
|
||||
import { InstanceFilterFollowStatus } from "@/types/enums";
|
||||
|
||||
const { result: dashboardResult } = useQuery<{ dashboard: IDashboard }>(
|
||||
DASHBOARD
|
||||
);
|
||||
|
||||
const dashboard = computed(() => dashboardResult.value?.dashboard);
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
useHead({
|
||||
title: computed(() => t("Administration")),
|
||||
});
|
||||
</script>
|
||||
@@ -78,12 +78,8 @@
|
||||
src="../../assets/logo.svg"
|
||||
alt=""
|
||||
/>
|
||||
<o-icon
|
||||
class="is-large"
|
||||
v-else
|
||||
custom-size="mdi-36px"
|
||||
icon="cloud-question"
|
||||
/>
|
||||
<CloudQuestion v-else :size="36" />
|
||||
|
||||
<div class="">
|
||||
<h4 class="text-lg truncate">{{ instance.domain }}</h4>
|
||||
<span
|
||||
@@ -183,6 +179,7 @@ import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { computed, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useHead } from "@vueuse/head";
|
||||
import CloudQuestion from "../../../node_modules/vue-material-design-icons/CloudQuestion.vue";
|
||||
|
||||
const INSTANCES_PAGE_LIMIT = 10;
|
||||
|
||||
|
||||
@@ -2,23 +2,23 @@
|
||||
<div>
|
||||
<breadcrumbs-nav
|
||||
:links="[
|
||||
{ name: RouteName.ADMIN, text: $t('Admin') },
|
||||
{ text: $t('Instance settings') },
|
||||
{ name: RouteName.ADMIN, text: t('Admin') },
|
||||
{ text: t('Instance settings') },
|
||||
]"
|
||||
/>
|
||||
|
||||
<section v-if="settingsToWrite">
|
||||
<form @submit.prevent="updateSettings">
|
||||
<o-field :label="$t('Instance Name')" label-for="instance-name">
|
||||
<o-field :label="t('Instance Name')" label-for="instance-name">
|
||||
<o-input v-model="settingsToWrite.instanceName" id="instance-name" />
|
||||
</o-field>
|
||||
<div class="field">
|
||||
<label class="label has-help" for="instance-description">{{
|
||||
$t("Instance Short Description")
|
||||
<div class="field flex flex-col">
|
||||
<label class="" for="instance-description">{{
|
||||
t("Instance Short Description")
|
||||
}}</label>
|
||||
<small>
|
||||
{{
|
||||
$t(
|
||||
t(
|
||||
"Displayed on homepage and meta tags. Describe what Mobilizon is and what makes this instance special in a single paragraph."
|
||||
)
|
||||
}}
|
||||
@@ -30,73 +30,71 @@
|
||||
id="instance-description"
|
||||
/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label has-help" for="instance-slogan">{{
|
||||
$t("Instance Slogan")
|
||||
<div class="field flex flex-col">
|
||||
<label class="" for="instance-slogan">{{
|
||||
t("Instance Slogan")
|
||||
}}</label>
|
||||
<small>
|
||||
{{
|
||||
$t(
|
||||
t(
|
||||
'A short tagline for your instance homepage. Defaults to "Gather ⋅ Organize ⋅ Mobilize"'
|
||||
)
|
||||
}}
|
||||
</small>
|
||||
<o-input
|
||||
v-model="settingsToWrite.instanceSlogan"
|
||||
:placeholder="$t('Gather ⋅ Organize ⋅ Mobilize')"
|
||||
:placeholder="t('Gather ⋅ Organize ⋅ Mobilize')"
|
||||
id="instance-slogan"
|
||||
/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label has-help" for="instance-contact">{{
|
||||
$t("Contact")
|
||||
}}</label>
|
||||
<div class="field flex flex-col">
|
||||
<label class="" for="instance-contact">{{ t("Contact") }}</label>
|
||||
<small>
|
||||
{{ $t("Can be an email or a link, or just plain text.") }}
|
||||
{{ t("Can be an email or a link, or just plain text.") }}
|
||||
</small>
|
||||
<o-input v-model="settingsToWrite.contact" id="instance-contact" />
|
||||
</div>
|
||||
<o-field :label="$t('Allow registrations')">
|
||||
<o-field :label="t('Allow registrations')">
|
||||
<o-switch v-model="settingsToWrite.registrationsOpen">
|
||||
<p
|
||||
class="prose dark:prose-invert"
|
||||
v-if="settingsToWrite.registrationsOpen"
|
||||
>
|
||||
{{ $t("Registration is allowed, anyone can register.") }}
|
||||
{{ t("Registration is allowed, anyone can register.") }}
|
||||
</p>
|
||||
<p class="prose dark:prose-invert" v-else>
|
||||
{{ $t("Registration is closed.") }}
|
||||
{{ t("Registration is closed.") }}
|
||||
</p>
|
||||
</o-switch>
|
||||
</o-field>
|
||||
<div class="field">
|
||||
<label class="label has-help" for="instance-languages">{{
|
||||
$t("Instance languages")
|
||||
<div class="field flex flex-col">
|
||||
<label class="" for="instance-languages">{{
|
||||
t("Instance languages")
|
||||
}}</label>
|
||||
<small>
|
||||
{{ $t("Main languages you/your moderators speak") }}
|
||||
{{ t("Main languages you/your moderators speak") }}
|
||||
</small>
|
||||
<o-taginput
|
||||
<o-inputitems
|
||||
v-model="instanceLanguages"
|
||||
:data="filteredLanguages"
|
||||
autocomplete
|
||||
:open-on-focus="true"
|
||||
field="name"
|
||||
icon="label"
|
||||
:placeholder="$t('Select languages')"
|
||||
:placeholder="t('Select languages')"
|
||||
@typing="getFilteredLanguages"
|
||||
id="instance-languages"
|
||||
>
|
||||
<template #empty>{{ $t("No languages found") }}</template>
|
||||
</o-taginput>
|
||||
<template #empty>{{ t("No languages found") }}</template>
|
||||
</o-inputitems>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label has-help" for="instance-long-description">{{
|
||||
$t("Instance Long Description")
|
||||
<div class="field flex flex-col">
|
||||
<label class="" for="instance-long-description">{{
|
||||
t("Instance Long Description")
|
||||
}}</label>
|
||||
<small>
|
||||
{{
|
||||
$t(
|
||||
t(
|
||||
"A place to explain who you are and the things that set your instance apart. You can use HTML tags."
|
||||
)
|
||||
}}
|
||||
@@ -108,13 +106,11 @@
|
||||
id="instance-long-description"
|
||||
/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label has-help" for="instance-rules">{{
|
||||
$t("Instance Rules")
|
||||
}}</label>
|
||||
<div class="field flex flex-col">
|
||||
<label class="" for="instance-rules">{{ t("Instance Rules") }}</label>
|
||||
<small>
|
||||
{{
|
||||
$t(
|
||||
t(
|
||||
"A place for your code of conduct, rules or guidelines. You can use HTML tags."
|
||||
)
|
||||
}}
|
||||
@@ -125,19 +121,19 @@
|
||||
id="instance-rules"
|
||||
/>
|
||||
</div>
|
||||
<o-field :label="$t('Instance Terms Source')">
|
||||
<div class="columns">
|
||||
<div class="column is-one-third-desktop">
|
||||
<o-field :label="t('Instance Terms Source')">
|
||||
<div class="">
|
||||
<div class="">
|
||||
<fieldset>
|
||||
<legend>
|
||||
{{ $t("Choose the source of the instance's Terms") }}
|
||||
{{ t("Choose the source of the instance's Terms") }}
|
||||
</legend>
|
||||
<o-field>
|
||||
<o-radio
|
||||
v-model="settingsToWrite.instanceTermsType"
|
||||
name="instanceTermsType"
|
||||
:native-value="InstanceTermsType.DEFAULT"
|
||||
>{{ $t("Default Mobilizon terms") }}</o-radio
|
||||
>{{ t("Default Mobilizon terms") }}</o-radio
|
||||
>
|
||||
</o-field>
|
||||
<o-field>
|
||||
@@ -145,7 +141,7 @@
|
||||
v-model="settingsToWrite.instanceTermsType"
|
||||
name="instanceTermsType"
|
||||
:native-value="InstanceTermsType.URL"
|
||||
>{{ $t("Custom URL") }}</o-radio
|
||||
>{{ t("Custom URL") }}</o-radio
|
||||
>
|
||||
</o-field>
|
||||
<o-field>
|
||||
@@ -153,20 +149,20 @@
|
||||
v-model="settingsToWrite.instanceTermsType"
|
||||
name="instanceTermsType"
|
||||
:native-value="InstanceTermsType.CUSTOM"
|
||||
>{{ $t("Custom text") }}</o-radio
|
||||
>{{ t("Custom text") }}</o-radio
|
||||
>
|
||||
</o-field>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div
|
||||
class="notification"
|
||||
<div class="">
|
||||
<o-notification
|
||||
class="bg-slate-700"
|
||||
v-if="
|
||||
settingsToWrite.instanceTermsType ===
|
||||
InstanceTermsType.DEFAULT
|
||||
"
|
||||
>
|
||||
<b>{{ $t("Default") }}</b>
|
||||
<b>{{ t("Default") }}</b>
|
||||
<i18n-t
|
||||
tag="p"
|
||||
class="prose dark:prose-invert"
|
||||
@@ -177,25 +173,25 @@
|
||||
href="https://demo.mobilizon.org/terms"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>{{ $t("default Mobilizon terms") }}</a
|
||||
>{{ t("default Mobilizon terms") }}</a
|
||||
>
|
||||
</template>
|
||||
</i18n-t>
|
||||
<b>{{
|
||||
$t(
|
||||
t(
|
||||
"NOTE! The default terms have not been checked over by a lawyer and thus are unlikely to provide full legal protection for all situations for an instance admin using them. They are also not specific to all countries and jurisdictions. If you are unsure, please check with a lawyer."
|
||||
)
|
||||
}}</b>
|
||||
</div>
|
||||
</o-notification>
|
||||
<div
|
||||
class="notification"
|
||||
v-if="
|
||||
settingsToWrite.instanceTermsType === InstanceTermsType.URL
|
||||
"
|
||||
>
|
||||
<b>{{ $t("URL") }}</b>
|
||||
<b>{{ t("URL") }}</b>
|
||||
<p class="prose dark:prose-invert">
|
||||
{{ $t("Set an URL to a page with your own terms.") }}
|
||||
{{ t("Set an URL to a page with your own terms.") }}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
@@ -204,7 +200,7 @@
|
||||
settingsToWrite.instanceTermsType === InstanceTermsType.CUSTOM
|
||||
"
|
||||
>
|
||||
<b>{{ $t("Custom") }}</b>
|
||||
<b>{{ t("Custom") }}</b>
|
||||
<i18n-t
|
||||
tag="p"
|
||||
class="prose dark:prose-invert"
|
||||
@@ -216,7 +212,7 @@
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
{{ $t("default Mobilizon terms") }}</a
|
||||
{{ t("default Mobilizon terms") }}</a
|
||||
>
|
||||
</template>
|
||||
</i18n-t>
|
||||
@@ -225,7 +221,7 @@
|
||||
</div>
|
||||
</o-field>
|
||||
<o-field
|
||||
:label="$t('Instance Terms URL')"
|
||||
:label="t('Instance Terms URL')"
|
||||
label-for="instanceTermsUrl"
|
||||
v-if="settingsToWrite.instanceTermsType === InstanceTermsType.URL"
|
||||
>
|
||||
@@ -236,7 +232,7 @@
|
||||
/>
|
||||
</o-field>
|
||||
<o-field
|
||||
:label="$t('Instance Terms')"
|
||||
:label="t('Instance Terms')"
|
||||
label-for="instanceTerms"
|
||||
v-if="settingsToWrite.instanceTermsType === InstanceTermsType.CUSTOM"
|
||||
>
|
||||
@@ -246,19 +242,19 @@
|
||||
id="instanceTerms"
|
||||
/>
|
||||
</o-field>
|
||||
<o-field :label="$t('Instance Privacy Policy Source')">
|
||||
<div class="columns">
|
||||
<div class="column is-one-third-desktop">
|
||||
<o-field :label="t('Instance Privacy Policy Source')">
|
||||
<div class="">
|
||||
<div class="">
|
||||
<fieldset>
|
||||
<legend>
|
||||
{{ $t("Choose the source of the instance's Privacy Policy") }}
|
||||
{{ t("Choose the source of the instance's Privacy Policy") }}
|
||||
</legend>
|
||||
<o-field>
|
||||
<o-radio
|
||||
v-model="settingsToWrite.instancePrivacyPolicyType"
|
||||
name="instancePrivacyType"
|
||||
:native-value="InstancePrivacyType.DEFAULT"
|
||||
>{{ $t("Default Mobilizon privacy policy") }}</o-radio
|
||||
>{{ t("Default Mobilizon privacy policy") }}</o-radio
|
||||
>
|
||||
</o-field>
|
||||
<o-field>
|
||||
@@ -266,7 +262,7 @@
|
||||
v-model="settingsToWrite.instancePrivacyPolicyType"
|
||||
name="instancePrivacyType"
|
||||
:native-value="InstancePrivacyType.URL"
|
||||
>{{ $t("Custom URL") }}</o-radio
|
||||
>{{ t("Custom URL") }}</o-radio
|
||||
>
|
||||
</o-field>
|
||||
<o-field>
|
||||
@@ -274,12 +270,12 @@
|
||||
v-model="settingsToWrite.instancePrivacyPolicyType"
|
||||
name="instancePrivacyType"
|
||||
:native-value="InstancePrivacyType.CUSTOM"
|
||||
>{{ $t("Custom text") }}</o-radio
|
||||
>{{ t("Custom text") }}</o-radio
|
||||
>
|
||||
</o-field>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="">
|
||||
<div
|
||||
class="notification"
|
||||
v-if="
|
||||
@@ -287,7 +283,7 @@
|
||||
InstancePrivacyType.DEFAULT
|
||||
"
|
||||
>
|
||||
<b>{{ $t("Default") }}</b>
|
||||
<b>{{ t("Default") }}</b>
|
||||
<i18n-t
|
||||
tag="p"
|
||||
class="prose dark:prose-invert"
|
||||
@@ -298,7 +294,7 @@
|
||||
href="https://demo.mobilizon.org/privacy"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>{{ $t("default Mobilizon privacy policy") }}</a
|
||||
>{{ t("default Mobilizon privacy policy") }}</a
|
||||
>
|
||||
</template>
|
||||
</i18n-t>
|
||||
@@ -310,9 +306,9 @@
|
||||
InstancePrivacyType.URL
|
||||
"
|
||||
>
|
||||
<b>{{ $t("URL") }}</b>
|
||||
<b>{{ t("URL") }}</b>
|
||||
<p class="prose dark:prose-invert">
|
||||
{{ $t("Set an URL to a page with your own privacy policy.") }}
|
||||
{{ t("Set an URL to a page with your own privacy policy.") }}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
@@ -322,11 +318,11 @@
|
||||
InstancePrivacyType.CUSTOM
|
||||
"
|
||||
>
|
||||
<b>{{ $t("Custom") }}</b>
|
||||
<b>{{ t("Custom") }}</b>
|
||||
<i18n-t
|
||||
tag="p"
|
||||
class="prose dark:prose-invert"
|
||||
path="Enter your own privacy policy. HTML tags allowed. The {mobilizon_privacy_policy} is provided as template."
|
||||
keypath="Enter your own privacy policy. HTML tags allowed. The {mobilizon_privacy_policy} is provided as template."
|
||||
>
|
||||
<template #mobilizon_privacy_policy>
|
||||
<a
|
||||
@@ -334,7 +330,7 @@
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
{{ $t("default Mobilizon privacy policy") }}</a
|
||||
{{ t("default Mobilizon privacy policy") }}</a
|
||||
>
|
||||
</template>
|
||||
</i18n-t>
|
||||
@@ -343,7 +339,7 @@
|
||||
</div>
|
||||
</o-field>
|
||||
<o-field
|
||||
:label="$t('Instance Privacy Policy URL')"
|
||||
:label="t('Instance Privacy Policy URL')"
|
||||
label-for="instancePrivacyPolicyUrl"
|
||||
v-if="
|
||||
settingsToWrite.instancePrivacyPolicyType ===
|
||||
@@ -357,7 +353,7 @@
|
||||
/>
|
||||
</o-field>
|
||||
<o-field
|
||||
:label="$t('Instance Privacy Policy')"
|
||||
:label="t('Instance Privacy Policy')"
|
||||
label-for="instancePrivacyPolicy"
|
||||
v-if="
|
||||
settingsToWrite.instancePrivacyPolicyType ===
|
||||
@@ -371,7 +367,7 @@
|
||||
/>
|
||||
</o-field>
|
||||
<o-button native-type="submit" variant="primary">{{
|
||||
$t("Save")
|
||||
t("Save")
|
||||
}}</o-button>
|
||||
</form>
|
||||
</section>
|
||||
@@ -390,29 +386,30 @@ import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { ref, computed, watch, inject } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@vueuse/head";
|
||||
import { Notifier } from "@/plugins/notifier";
|
||||
import type { Notifier } from "@/plugins/notifier";
|
||||
|
||||
const defaultAdminSettings: IAdminSettings = {
|
||||
instanceName: "",
|
||||
instanceDescription: "",
|
||||
instanceSlogan: "",
|
||||
instanceLongDescription: "",
|
||||
contact: "",
|
||||
instanceTerms: "",
|
||||
instanceTermsType: InstanceTermsType.DEFAULT,
|
||||
instanceTermsUrl: null,
|
||||
instancePrivacyPolicy: "",
|
||||
instancePrivacyPolicyType: InstancePrivacyType.DEFAULT,
|
||||
instancePrivacyPolicyUrl: null,
|
||||
instanceRules: "",
|
||||
registrationsOpen: false,
|
||||
instanceLanguages: [],
|
||||
};
|
||||
|
||||
const { result: adminSettingsResult } = useQuery<{
|
||||
adminSettings: IAdminSettings;
|
||||
}>(ADMIN_SETTINGS);
|
||||
const adminSettings = computed(
|
||||
() =>
|
||||
adminSettingsResult.value?.adminSettings ?? {
|
||||
instanceName: "",
|
||||
instanceDescription: "",
|
||||
instanceSlogan: "",
|
||||
instanceLongDescription: "",
|
||||
contact: "",
|
||||
instanceTerms: "",
|
||||
instanceTermsType: InstanceTermsType.DEFAULT,
|
||||
instanceTermsUrl: null,
|
||||
instancePrivacyPolicy: "",
|
||||
instancePrivacyPolicyType: InstanceTermsType.DEFAULT,
|
||||
instancePrivacyPolicyUrl: null,
|
||||
instanceRules: "",
|
||||
registrationsOpen: false,
|
||||
instanceLanguages: [],
|
||||
}
|
||||
() => adminSettingsResult.value?.adminSettings ?? defaultAdminSettings
|
||||
);
|
||||
|
||||
const { result: languageResult } = useQuery<{ languages: ILanguage[] }>(
|
||||
@@ -425,10 +422,10 @@ useHead({
|
||||
title: computed(() => t("Settings")),
|
||||
});
|
||||
|
||||
const settingsToWrite = ref<IAdminSettings>({ ...adminSettings });
|
||||
const settingsToWrite = ref<IAdminSettings>(defaultAdminSettings);
|
||||
|
||||
watch(adminSettings, () => {
|
||||
// settingsToWrite.value = { ...adminSettings.value };
|
||||
settingsToWrite.value = { ...adminSettings.value };
|
||||
});
|
||||
|
||||
const filteredLanguages = ref<string[]>([]);
|
||||
|
||||
@@ -196,7 +196,6 @@ a.user-profile {
|
||||
text-decoration: none;
|
||||
}
|
||||
a.disabled {
|
||||
color: $danger;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -496,7 +496,6 @@
|
||||
<style lang="scss" scoped>
|
||||
// @use "@/styles/_mixins" as *;
|
||||
// main section > .container {
|
||||
// // background: $white;
|
||||
|
||||
// form {
|
||||
// h2 {
|
||||
@@ -528,7 +527,6 @@
|
||||
// span {
|
||||
// padding: 5px 7px;
|
||||
// display: inline;
|
||||
// background: $secondary;
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -553,7 +551,6 @@
|
||||
|
||||
// nav.navbar {
|
||||
// min-height: 2rem !important;
|
||||
// background: lighten($secondary, 10%);
|
||||
|
||||
// .container {
|
||||
// min-height: 2rem;
|
||||
@@ -561,7 +558,6 @@
|
||||
// .navbar-menu,
|
||||
// .navbar-end {
|
||||
// display: flex !important;
|
||||
// background: lighten($secondary, 10%);
|
||||
// }
|
||||
|
||||
// .navbar-end {
|
||||
@@ -625,7 +621,6 @@ import {
|
||||
CREATE_EVENT,
|
||||
EDIT_EVENT,
|
||||
EVENT_PERSON_PARTICIPATION,
|
||||
FETCH_EVENT,
|
||||
} from "../../graphql/event";
|
||||
import {
|
||||
EventModel,
|
||||
@@ -634,20 +629,8 @@ import {
|
||||
removeTypeName,
|
||||
toEditJSON,
|
||||
} from "../../types/event.model";
|
||||
import {
|
||||
CURRENT_ACTOR_CLIENT,
|
||||
IDENTITIES,
|
||||
LOGGED_USER_DRAFTS,
|
||||
PERSON_STATUS_GROUP,
|
||||
} from "../../graphql/actor";
|
||||
import { FETCH_GROUP } from "../../graphql/group";
|
||||
import {
|
||||
displayNameAndUsername,
|
||||
IActor,
|
||||
IGroup,
|
||||
IPerson,
|
||||
usernameWithDomain,
|
||||
} from "../../types/actor";
|
||||
import { LOGGED_USER_DRAFTS } from "../../graphql/actor";
|
||||
import { IActor, IGroup, IPerson, usernameWithDomain } from "../../types/actor";
|
||||
import {
|
||||
buildFileFromIMedia,
|
||||
buildFileVariable,
|
||||
@@ -655,8 +638,6 @@ import {
|
||||
} from "../../utils/image";
|
||||
import RouteName from "../../router/name";
|
||||
import "intersection-observer";
|
||||
import { CONFIG_EDIT_EVENT } from "../../graphql/config";
|
||||
import { IConfig } from "../../types/config.model";
|
||||
import {
|
||||
ApolloCache,
|
||||
FetchResult,
|
||||
@@ -664,8 +645,6 @@ import {
|
||||
} from "@apollo/client/core";
|
||||
import cloneDeep from "lodash/cloneDeep";
|
||||
import { IEventOptions } from "@/types/event-options.model";
|
||||
import { USER_SETTINGS } from "@/graphql/user";
|
||||
import { IUser } from "@/types/current-user.model";
|
||||
import { IAddress } from "@/types/address.model";
|
||||
import { LOGGED_USER_PARTICIPATIONS } from "@/graphql/participant";
|
||||
import {
|
||||
@@ -690,6 +669,7 @@ import { Dialog } from "@/plugins/dialog";
|
||||
import { Notifier } from "@/plugins/notifier";
|
||||
import { useHead } from "@vueuse/head";
|
||||
import { useProgrammatic } from "@oruga-ui/oruga-next";
|
||||
import type { Locale } from "date-fns";
|
||||
|
||||
const DEFAULT_LIMIT_NUMBER_OF_PLACES = 10;
|
||||
|
||||
@@ -1033,10 +1013,10 @@ const handleError = (err: any) => {
|
||||
* Put in cache the updated or created event.
|
||||
* If the event is not a draft anymore, also put in cache the participation
|
||||
*/
|
||||
const postCreateOrUpdate = (store: any, updateEvent: IEvent) => {
|
||||
const resultEvent: IEvent = { ...updateEvent };
|
||||
const postCreateOrUpdate = (store: any, updatedEvent: IEvent) => {
|
||||
const resultEvent: IEvent = { ...updatedEvent };
|
||||
console.debug("resultEvent", resultEvent);
|
||||
if (!updateEvent.draft) {
|
||||
if (!updatedEvent.draft) {
|
||||
store.writeQuery({
|
||||
query: EVENT_PERSON_PARTICIPATION,
|
||||
variables: {
|
||||
@@ -1077,9 +1057,9 @@ const postCreateOrUpdate = (store: any, updateEvent: IEvent) => {
|
||||
*/
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
const postRefetchQueries = (
|
||||
updateEvent: IEvent
|
||||
updatedEvent: IEvent
|
||||
): InternalRefetchQueriesInclude => {
|
||||
if (updateEvent.draft) {
|
||||
if (updatedEvent.draft) {
|
||||
return [
|
||||
{
|
||||
query: LOGGED_USER_DRAFTS,
|
||||
@@ -1253,10 +1233,10 @@ const beginsOn = computed({
|
||||
// }
|
||||
return event.value.beginsOn ? new Date(event.value.beginsOn) : null;
|
||||
},
|
||||
set(beginsOn: Date | null) {
|
||||
event.value.beginsOn = beginsOn?.toISOString() ?? null;
|
||||
if (!event.value.endsOn || !beginsOn) return;
|
||||
const dateBeginsOn = new Date(beginsOn);
|
||||
set(newBeginsOn: Date | null) {
|
||||
event.value.beginsOn = newBeginsOn?.toISOString() ?? null;
|
||||
if (!event.value.endsOn || !newBeginsOn) return;
|
||||
const dateBeginsOn = new Date(newBeginsOn);
|
||||
const dateEndsOn = new Date(event.value.endsOn);
|
||||
let endsOn = new Date(event.value.endsOn);
|
||||
if (dateEndsOn < dateBeginsOn) {
|
||||
@@ -1277,8 +1257,8 @@ const endsOn = computed({
|
||||
// }
|
||||
return event.value.endsOn ? new Date(event.value.endsOn) : null;
|
||||
},
|
||||
set(endsOn: Date | null) {
|
||||
event.value.endsOn = endsOn?.toISOString() ?? null;
|
||||
set(newEndsOn: Date | null) {
|
||||
event.value.endsOn = newEndsOn?.toISOString() ?? null;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1324,10 +1304,10 @@ const timezone = computed({
|
||||
get(): string | null {
|
||||
return event.value.options.timezone;
|
||||
},
|
||||
set(timezone: string | null) {
|
||||
set(newTimezone: string | null) {
|
||||
event.value.options = {
|
||||
...event.value.options,
|
||||
timezone,
|
||||
timezone: newTimezone,
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -1368,10 +1348,10 @@ const isOnline = computed({
|
||||
get(): boolean {
|
||||
return event.value.options.isOnline;
|
||||
},
|
||||
set(isOnline: boolean) {
|
||||
set(newIsOnline: boolean) {
|
||||
event.value.options = {
|
||||
...event.value.options,
|
||||
isOnline,
|
||||
isOnline: newIsOnline,
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -1391,13 +1371,13 @@ onFetchEventResult((result) => {
|
||||
}
|
||||
});
|
||||
|
||||
const { person } = usePersonStatusGroup(
|
||||
const groupFederatedUsername = computed(() =>
|
||||
usernameWithDomain(fetchedEvent.value?.attributedTo)
|
||||
);
|
||||
|
||||
const { group } = useGroup(
|
||||
usernameWithDomain(fetchedEvent.value?.attributedTo)
|
||||
);
|
||||
const { person } = usePersonStatusGroup(groupFederatedUsername);
|
||||
|
||||
const { group } = useGroup(groupFederatedUsername);
|
||||
|
||||
watch(group, () => {
|
||||
if (!props.isUpdate && group.value?.visibility == GroupVisibility.UNLISTED) {
|
||||
|
||||
@@ -1339,7 +1339,6 @@ div.sidebar {
|
||||
a {
|
||||
display: inline-block;
|
||||
padding: 0.3rem;
|
||||
background: $secondary;
|
||||
color: #111;
|
||||
|
||||
&:empty {
|
||||
|
||||
@@ -416,8 +416,6 @@ const firstDayOfWeek = computed((): number => {
|
||||
// @import "node_modules/bulma/sass/utilities/mixins.sass";
|
||||
|
||||
main > .container {
|
||||
// background: $white;
|
||||
|
||||
& > h1 {
|
||||
margin: 10px auto 5px;
|
||||
}
|
||||
@@ -436,7 +434,6 @@ section {
|
||||
font-size: 1.3rem;
|
||||
|
||||
&::after {
|
||||
background: $orange-3;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
@@ -456,7 +456,6 @@ const openDetailedRows = <Record<string, boolean>>{};
|
||||
<style lang="scss" scoped>
|
||||
section.container.container {
|
||||
padding: 1rem;
|
||||
// background: $white;
|
||||
}
|
||||
|
||||
.table {
|
||||
@@ -479,12 +478,6 @@ section.container.container {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
span.tag {
|
||||
&.is-primary {
|
||||
background-color: $primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nav.breadcrumb {
|
||||
|
||||
@@ -135,7 +135,10 @@
|
||||
currentActor?.id !== undefined
|
||||
"
|
||||
>
|
||||
<button class="media py-4 px-2 w-full" @click="followGroup">
|
||||
<button
|
||||
class="flex gap-1 text-start py-4 px-2 w-full"
|
||||
@click="followGroup"
|
||||
>
|
||||
<RSS />
|
||||
<div class="pl-2">
|
||||
<h3 class="font-medium text-lg">{{ t("Follow") }}</h3>
|
||||
@@ -174,7 +177,10 @@
|
||||
isGroupInviteOnly || isCurrentActorAPendingGroupMember
|
||||
"
|
||||
>
|
||||
<button class="media py-4 px-2 w-full" @click="joinGroup">
|
||||
<button
|
||||
class="flex gap-1 text-start py-4 px-2 w-full"
|
||||
@click="joinGroup"
|
||||
>
|
||||
<AccountMultiplePlus />
|
||||
<div class="pl-2">
|
||||
<h3 class="font-medium text-lg">{{ t("Join") }}</h3>
|
||||
@@ -346,7 +352,7 @@
|
||||
</o-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<invitations
|
||||
<InvitationsList
|
||||
v-if="
|
||||
isCurrentActorAnInvitedGroupMember && groupMember !== undefined
|
||||
"
|
||||
@@ -626,7 +632,7 @@ import {
|
||||
import EventMinimalistCard from "@/components/Event/EventMinimalistCard.vue";
|
||||
import MultiPostListItem from "@/components/Post/MultiPostListItem.vue";
|
||||
import { Address, addressFullName } from "@/types/address.model";
|
||||
import Invitations from "@/components/Group/Invitations.vue";
|
||||
import InvitationsList from "@/components/Group/InvitationsList.vue";
|
||||
import addMinutes from "date-fns/addMinutes";
|
||||
import { JOIN_GROUP } from "@/graphql/member";
|
||||
import { MemberRole, Openness, PostVisibility } from "@/types/enums";
|
||||
@@ -1129,7 +1135,6 @@ watch(isCurrentActorAGroupMember, () => {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@use "@/styles/_mixins" as *;
|
||||
// @import "node_modules/bulma/sass/utilities/mixins.sass";
|
||||
div.container {
|
||||
.block-container {
|
||||
display: flex;
|
||||
@@ -1137,21 +1142,10 @@ div.container {
|
||||
margin-top: 15px;
|
||||
|
||||
&.presentation {
|
||||
border: 2px solid $purple-2;
|
||||
padding: 0 0 10px;
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
|
||||
// h1 {
|
||||
// color: $purple-1;
|
||||
// font-size: 2rem;
|
||||
// font-weight: 500;
|
||||
// }
|
||||
|
||||
.button.is-outlined {
|
||||
border-color: $purple-2;
|
||||
}
|
||||
|
||||
& > *:not(img) {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
@@ -403,7 +403,7 @@ const confirmDeleteGroup = (): void => {
|
||||
),
|
||||
confirmText: t("Delete group"),
|
||||
cancelText: t("Cancel"),
|
||||
type: "danger",
|
||||
variant: "danger",
|
||||
hasIcon: true,
|
||||
onConfirm: () =>
|
||||
deleteGroupMutation({
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
>
|
||||
</div>
|
||||
<o-loading v-model:active="loading"></o-loading>
|
||||
<invitations
|
||||
<InvitationsList
|
||||
:invitations="invitations"
|
||||
@accept-invitation="acceptInvitation"
|
||||
@reject-invitation="rejectInvitation"
|
||||
@@ -82,8 +82,8 @@
|
||||
import { LOGGED_USER_MEMBERSHIPS } from "@/graphql/actor";
|
||||
import { LEAVE_GROUP } from "@/graphql/group";
|
||||
import GroupMemberCard from "@/components/Group/GroupMemberCard.vue";
|
||||
import Invitations from "@/components/Group/Invitations.vue";
|
||||
import { IGroup, usernameWithDomain } from "@/types/actor";
|
||||
import InvitationsList from "@/components/Group/InvitationsList.vue";
|
||||
import { usernameWithDomain } from "@/types/actor";
|
||||
import { IMember } from "@/types/actor/member.model";
|
||||
import { MemberRole } from "@/types/enums";
|
||||
import { supportsWebPFormat } from "@/utils/support";
|
||||
|
||||
@@ -43,12 +43,3 @@ useHead({
|
||||
title: computed(() => t("Group settings")),
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
aside.section {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
.container.section {
|
||||
background: $white;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -288,12 +288,12 @@
|
||||
<script lang="ts" setup>
|
||||
import { EventSortField, ParticipantRole, SortDirection } from "@/types/enums";
|
||||
import { Paginate } from "@/types/paginate";
|
||||
import { IParticipant, Participant } from "../types/participant.model";
|
||||
import { IParticipant } from "../types/participant.model";
|
||||
import { FETCH_EVENTS } from "../graphql/event";
|
||||
import EventParticipationCard from "../components/Event/EventParticipationCard.vue";
|
||||
import MultiCard from "../components/Event/MultiCard.vue";
|
||||
import { CURRENT_ACTOR_CLIENT } from "../graphql/actor";
|
||||
import { displayName, IPerson, Person } from "../types/actor";
|
||||
import { IPerson, Person } from "../types/actor";
|
||||
import ngeohash from "ngeohash";
|
||||
import {
|
||||
ICurrentUser,
|
||||
@@ -471,10 +471,8 @@ const locationName = computed(
|
||||
// () => closeEventsResult.value?.searchEvents || { total: 0, elements: [] }
|
||||
// );
|
||||
|
||||
const currentUserParticipations = computed(() =>
|
||||
loggedUser.value?.participations.elements.map(
|
||||
(participation: IParticipant) => new Participant(participation)
|
||||
)
|
||||
const currentUserParticipations = computed(
|
||||
() => loggedUser.value?.participations.elements
|
||||
);
|
||||
|
||||
const instanceName = computed((): string | undefined => config.value?.name);
|
||||
@@ -635,6 +633,6 @@ watch(loggedUser, (loggedUserValue) => {
|
||||
// },
|
||||
|
||||
useHead({
|
||||
title: computed(() => instanceName.value),
|
||||
title: computed(() => instanceName.value ?? ""),
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -99,8 +99,3 @@ useHead({
|
||||
title: computed(() => t("Interact with a remote content")),
|
||||
});
|
||||
</script>
|
||||
<style lang="scss">
|
||||
main > .container {
|
||||
background: $white;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -214,7 +214,7 @@
|
||||
log.object.__typename == 'Group'
|
||||
"
|
||||
tag="span"
|
||||
path="{moderator} suspended group {profile}"
|
||||
keypath="{moderator} suspended group {profile}"
|
||||
>
|
||||
<template #moderator>
|
||||
<router-link
|
||||
|
||||
@@ -515,10 +515,6 @@ tbody td img.image,
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.report-content {
|
||||
border-left: 4px solid $primary;
|
||||
}
|
||||
|
||||
.box a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
|
||||
@@ -411,7 +411,6 @@ useHead({
|
||||
form {
|
||||
nav.navbar {
|
||||
// min-height: 2rem !important;
|
||||
background: lighten($secondary, 10%);
|
||||
|
||||
.container {
|
||||
// min-height: 2rem;
|
||||
@@ -419,7 +418,6 @@ form {
|
||||
.navbar-menu,
|
||||
.navbar-end {
|
||||
// display: flex !important;
|
||||
background: lighten($secondary, 10%);
|
||||
// flex-wrap: wrap;
|
||||
}
|
||||
|
||||
|
||||
@@ -416,7 +416,6 @@ onDeletePostDone(({ data }) => {
|
||||
<style lang="scss" scoped>
|
||||
@use "@/styles/_mixins" as *;
|
||||
article.post {
|
||||
// background: $white !important;
|
||||
header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -487,7 +486,6 @@ article.post {
|
||||
height: 0.2rem;
|
||||
content: " ";
|
||||
display: block;
|
||||
background-color: $purple-1;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
|
||||
@@ -250,10 +250,10 @@ import RouteName from "../../router/name";
|
||||
import { logout, SELECTED_PROVIDERS } from "../../utils/auth";
|
||||
import { useProgrammatic } from "@oruga-ui/oruga-next";
|
||||
|
||||
const { loggedUser } = useLoggedUser();
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
const { loggedUser } = useLoggedUser();
|
||||
|
||||
useHead({
|
||||
title: computed(() => t("General settings")),
|
||||
});
|
||||
|
||||
@@ -832,9 +832,7 @@ const { mutate: createNewFeedToken } = useMutation(CREATE_FEED_TOKEN, () => ({
|
||||
}
|
||||
|
||||
a.change-timezone {
|
||||
color: $primary;
|
||||
text-decoration: underline;
|
||||
text-decoration-color: #fea72b;
|
||||
text-decoration-thickness: 2px;
|
||||
@include margin-left(5px);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="container mx-auto">
|
||||
<h1 class="">{{ t("Settings") }}</h1>
|
||||
<h1 class="text-violet-3">{{ t("Settings") }}</h1>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<SettingsMenu class="max-w-xs w-full" />
|
||||
<div class="flex-1">
|
||||
|
||||
Reference in New Issue
Block a user