Show user and actors media usage in admin
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
51e760485b
commit
6c0a4c0d7d
@ -10,6 +10,7 @@ export const FETCH_PERSON = gql`
|
|||||||
summary
|
summary
|
||||||
preferredUsername
|
preferredUsername
|
||||||
suspended
|
suspended
|
||||||
|
mediaSize
|
||||||
avatar {
|
avatar {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@ -51,6 +52,7 @@ export const GET_PERSON = gql`
|
|||||||
summary
|
summary
|
||||||
preferredUsername
|
preferredUsername
|
||||||
suspended
|
suspended
|
||||||
|
mediaSize
|
||||||
avatar {
|
avatar {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
@ -84,6 +84,7 @@ export const GROUP_FIELDS_FRAGMENTS = gql`
|
|||||||
id
|
id
|
||||||
url
|
url
|
||||||
}
|
}
|
||||||
|
mediaSize
|
||||||
organizedEvents(
|
organizedEvents(
|
||||||
afterDatetime: $afterDateTime
|
afterDatetime: $afterDateTime
|
||||||
beforeDatetime: $beforeDateTime
|
beforeDatetime: $beforeDateTime
|
||||||
|
@ -200,6 +200,7 @@ export const GET_USER = gql`
|
|||||||
currentSignInAt
|
currentSignInAt
|
||||||
locale
|
locale
|
||||||
disabled
|
disabled
|
||||||
|
mediaSize
|
||||||
defaultActor {
|
defaultActor {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
@ -799,5 +799,6 @@
|
|||||||
"Mobilizon uses a system of profiles to compartiment your activities. You will be able to create as many profiles as you want.": "Mobilizon uses a system of profiles to compartiment your activities. You will be able to create as many profiles as you want.",
|
"Mobilizon uses a system of profiles to compartiment your activities. You will be able to create as many profiles as you want.": "Mobilizon uses a system of profiles to compartiment your activities. You will be able to create as many profiles as you want.",
|
||||||
"Mobilizon is a federated software, meaning you can interact - depending on your admin's federation settings - with content from other instances, such as joining groups or events that were created elsewhere.": "Mobilizon is a federated software, meaning you can interact - depending on your admin federation settings - with content from other instances, such as joining groups or events that were created elsewhere.",
|
"Mobilizon is a federated software, meaning you can interact - depending on your admin's federation settings - with content from other instances, such as joining groups or events that were created elsewhere.": "Mobilizon is a federated software, meaning you can interact - depending on your admin federation settings - with content from other instances, such as joining groups or events that were created elsewhere.",
|
||||||
"This instance, <b>{instanceName} ({domain})</b>, hosts your profile, so remember its name.": "This instance, <b>{instanceName} ({domain})</b>, hosts your profile, so remember its name.",
|
"This instance, <b>{instanceName} ({domain})</b>, hosts your profile, so remember its name.": "This instance, <b>{instanceName} ({domain})</b>, hosts your profile, so remember its name.",
|
||||||
"If you are being asked for your federated indentity, it's composed of your username and your instance. For instance, the federated identity for your first profile is:": "If you are being asked for your federated indentity, it's composed of your username and your instance. For instance, the federated identity for your first profile is:"
|
"If you are being asked for your federated indentity, it's composed of your username and your instance. For instance, the federated identity for your first profile is:": "If you are being asked for your federated indentity, it's composed of your username and your instance. For instance, the federated identity for your first profile is:",
|
||||||
|
"Uploaded media size": "Uploaded media size"
|
||||||
}
|
}
|
||||||
|
@ -887,5 +887,6 @@
|
|||||||
"Mobilizon uses a system of profiles to compartiment your activities. You will be able to create as many profiles as you want.": "Mobilizon utilise un système de profils pour compartimenter vos activités. Vous pourrez créer autant de profils que vous voulez.",
|
"Mobilizon uses a system of profiles to compartiment your activities. You will be able to create as many profiles as you want.": "Mobilizon utilise un système de profils pour compartimenter vos activités. Vous pourrez créer autant de profils que vous voulez.",
|
||||||
"Mobilizon is a federated software, meaning you can interact - depending on your admin's federation settings - with content from other instances, such as joining groups or events that were created elsewhere.": "Mobilizon est un logiciel fédéré, ce qui signifie que vous pouvez interagir - en fonction des paramètres de fédération de votre administrateur·ice - avec du contenu d'autres instances, comme par exemple rejoindre des groupes ou des événements ayant été créés ailleurs.",
|
"Mobilizon is a federated software, meaning you can interact - depending on your admin's federation settings - with content from other instances, such as joining groups or events that were created elsewhere.": "Mobilizon est un logiciel fédéré, ce qui signifie que vous pouvez interagir - en fonction des paramètres de fédération de votre administrateur·ice - avec du contenu d'autres instances, comme par exemple rejoindre des groupes ou des événements ayant été créés ailleurs.",
|
||||||
"This instance, <b>{instanceName} ({domain})</b>, hosts your profile, so remember its name.": "Cette instance, <b>{instanceName} ({domain})</b>, héberge votre profil, donc notez bien son nom.",
|
"This instance, <b>{instanceName} ({domain})</b>, hosts your profile, so remember its name.": "Cette instance, <b>{instanceName} ({domain})</b>, héberge votre profil, donc notez bien son nom.",
|
||||||
"If you are being asked for your federated indentity, it's composed of your username and your instance. For instance, the federated identity for your first profile is:": "Si l'on vous demande votre identité fédérée, elle est composée de votre nom d'utilisateur·ice et de votre instance. Par exemple, l'identité fédérée de votre premier profil est :"
|
"If you are being asked for your federated indentity, it's composed of your username and your instance. For instance, the federated identity for your first profile is:": "Si l'on vous demande votre identité fédérée, elle est composée de votre nom d'utilisateur·ice et de votre instance. Par exemple, l'identité fédérée de votre premier profil est :",
|
||||||
|
"Uploaded media size": "Taille des médias téléversés"
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ export interface IActor {
|
|||||||
url: string;
|
url: string;
|
||||||
name: string;
|
name: string;
|
||||||
domain: string | null;
|
domain: string | null;
|
||||||
|
mediaSize: number;
|
||||||
summary: string;
|
summary: string;
|
||||||
preferredUsername: string;
|
preferredUsername: string;
|
||||||
suspended: boolean;
|
suspended: boolean;
|
||||||
@ -30,6 +31,8 @@ export class Actor implements IActor {
|
|||||||
|
|
||||||
domain: string | null = null;
|
domain: string | null = null;
|
||||||
|
|
||||||
|
mediaSize = 0;
|
||||||
|
|
||||||
name = "";
|
name = "";
|
||||||
|
|
||||||
preferredUsername = "";
|
preferredUsername = "";
|
||||||
|
@ -39,6 +39,7 @@ export interface IUser extends ICurrentUser {
|
|||||||
actors: IPerson[];
|
actors: IPerson[];
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
participations: Paginate<IParticipant>;
|
participations: Paginate<IParticipant>;
|
||||||
|
mediaSize: number;
|
||||||
drafts: IEvent[];
|
drafts: IEvent[];
|
||||||
settings: IUserSettings;
|
settings: IUserSettings;
|
||||||
locale: string;
|
locale: string;
|
||||||
|
@ -18,4 +18,17 @@ function localeShortWeekDayNames(): string[] {
|
|||||||
return weekDayNames;
|
return weekDayNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { localeMonthNames, localeShortWeekDayNames };
|
// https://stackoverflow.com/a/18650828/10204399
|
||||||
|
function formatBytes(bytes: number, decimals = 2): string {
|
||||||
|
if (bytes === 0) return "0 Bytes";
|
||||||
|
|
||||||
|
const k = 1024;
|
||||||
|
const dm = decimals < 0 ? 0 : decimals;
|
||||||
|
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
||||||
|
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
|
||||||
|
return `${parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { localeMonthNames, localeShortWeekDayNames, formatBytes };
|
||||||
|
@ -198,6 +198,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue, Prop } from "vue-property-decorator";
|
import { Component, Vue, Prop } from "vue-property-decorator";
|
||||||
import { GET_GROUP, REFRESH_PROFILE } from "@/graphql/group";
|
import { GET_GROUP, REFRESH_PROFILE } from "@/graphql/group";
|
||||||
|
import { formatBytes } from "@/utils/datetime";
|
||||||
import { SUSPEND_PROFILE, UNSUSPEND_PROFILE } from "../../graphql/actor";
|
import { SUSPEND_PROFILE, UNSUSPEND_PROFILE } from "../../graphql/actor";
|
||||||
import { IGroup, MemberRole } from "../../types/actor";
|
import { IGroup, MemberRole } from "../../types/actor";
|
||||||
import { usernameWithDomain, IActor } from "../../types/actor/actor.model";
|
import { usernameWithDomain, IActor } from "../../types/actor/actor.model";
|
||||||
@ -258,6 +259,10 @@ export default class AdminGroupProfile extends Vue {
|
|||||||
key: this.$t("Domain") as string,
|
key: this.$t("Domain") as string,
|
||||||
value: (this.group.domain ? this.group.domain : this.$t("Local")) as string,
|
value: (this.group.domain ? this.group.domain : this.$t("Local")) as string,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: this.$i18n.t("Uploaded media size") as string,
|
||||||
|
value: formatBytes(this.group.mediaSize),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -126,11 +126,11 @@
|
|||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue, Prop } from "vue-property-decorator";
|
import { Component, Vue, Prop } from "vue-property-decorator";
|
||||||
|
import { formatBytes } from "@/utils/datetime";
|
||||||
import { GET_PERSON, SUSPEND_PROFILE, UNSUSPEND_PROFILE } from "../../graphql/actor";
|
import { GET_PERSON, SUSPEND_PROFILE, UNSUSPEND_PROFILE } from "../../graphql/actor";
|
||||||
import { IPerson } from "../../types/actor";
|
import { IPerson } from "../../types/actor";
|
||||||
import { usernameWithDomain } from "../../types/actor/actor.model";
|
import { usernameWithDomain } from "../../types/actor/actor.model";
|
||||||
import RouteName from "../../router/name";
|
import RouteName from "../../router/name";
|
||||||
import { IEvent } from "../../types/event.model";
|
|
||||||
import ActorCard from "../../components/Account/ActorCard.vue";
|
import ActorCard from "../../components/Account/ActorCard.vue";
|
||||||
|
|
||||||
const EVENTS_PER_PAGE = 10;
|
const EVENTS_PER_PAGE = 10;
|
||||||
@ -171,9 +171,9 @@ export default class AdminProfile extends Vue {
|
|||||||
|
|
||||||
participationsPage = 1;
|
participationsPage = 1;
|
||||||
|
|
||||||
get metadata(): Array<object> {
|
get metadata(): Array<Record<string, unknown>> {
|
||||||
if (!this.person) return [];
|
if (!this.person) return [];
|
||||||
const res: object[] = [
|
const res: Record<string, unknown>[] = [
|
||||||
{
|
{
|
||||||
key: this.$t("Status") as string,
|
key: this.$t("Status") as string,
|
||||||
value: this.person.suspended ? this.$t("Suspended") : this.$t("Active"),
|
value: this.person.suspended ? this.$t("Suspended") : this.$t("Active"),
|
||||||
@ -182,6 +182,10 @@ export default class AdminProfile extends Vue {
|
|||||||
key: this.$t("Domain") as string,
|
key: this.$t("Domain") as string,
|
||||||
value: this.person.domain ? this.person.domain : this.$t("Local"),
|
value: this.person.domain ? this.person.domain : this.$t("Local"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: this.$i18n.t("Uploaded media size"),
|
||||||
|
value: formatBytes(this.person.mediaSize),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
if (!this.person.domain && this.person.user) {
|
if (!this.person.domain && this.person.user) {
|
||||||
res.push({
|
res.push({
|
||||||
@ -193,7 +197,7 @@ export default class AdminProfile extends Vue {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async suspendProfile() {
|
async suspendProfile(): Promise<void> {
|
||||||
this.$apollo.mutate<{ suspendProfile: { id: string } }>({
|
this.$apollo.mutate<{ suspendProfile: { id: string } }>({
|
||||||
mutation: SUSPEND_PROFILE,
|
mutation: SUSPEND_PROFILE,
|
||||||
variables: {
|
variables: {
|
||||||
@ -229,7 +233,7 @@ export default class AdminProfile extends Vue {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async unsuspendProfile() {
|
async unsuspendProfile(): Promise<void> {
|
||||||
const profileID = this.id;
|
const profileID = this.id;
|
||||||
this.$apollo.mutate<{ unsuspendProfile: { id: string } }>({
|
this.$apollo.mutate<{ unsuspendProfile: { id: string } }>({
|
||||||
mutation: UNSUSPEND_PROFILE,
|
mutation: UNSUSPEND_PROFILE,
|
||||||
@ -249,7 +253,7 @@ export default class AdminProfile extends Vue {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async onOrganizedEventsPageChange(page: number) {
|
async onOrganizedEventsPageChange(page: number): Promise<void> {
|
||||||
this.organizedEventsPage = page;
|
this.organizedEventsPage = page;
|
||||||
await this.$apollo.queries.person.fetchMore({
|
await this.$apollo.queries.person.fetchMore({
|
||||||
variables: {
|
variables: {
|
||||||
@ -274,7 +278,7 @@ export default class AdminProfile extends Vue {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async onParticipationsPageChange(page: number) {
|
async onParticipationsPageChange(page: number): Promise<void> {
|
||||||
this.participationsPage = page;
|
this.participationsPage = page;
|
||||||
await this.$apollo.queries.person.fetchMore({
|
await this.$apollo.queries.person.fetchMore({
|
||||||
variables: {
|
variables: {
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
</nav>
|
</nav>
|
||||||
<table v-if="metadata.length > 0" class="table is-fullwidth">
|
<table v-if="metadata.length > 0" class="table is-fullwidth">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="{ key, value, link, elements } in metadata" :key="key">
|
<tr v-for="{ key, value, link, elements, type } in metadata" :key="key">
|
||||||
<td>{{ key }}</td>
|
<td>{{ key }}</td>
|
||||||
<td v-if="elements && elements.length > 0">
|
<td v-if="elements && elements.length > 0">
|
||||||
<ul v-for="{ value, link: elementLink, active } in elements" :key="value">
|
<ul v-for="{ value, link: elementLink, active } in elements" :key="value">
|
||||||
@ -46,6 +46,9 @@
|
|||||||
{{ value }}
|
{{ value }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</td>
|
</td>
|
||||||
|
<td v-else-if="type == 'code'">
|
||||||
|
<code>{{ value }}</code>
|
||||||
|
</td>
|
||||||
<td v-else>{{ value }}</td>
|
<td v-else>{{ value }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -60,6 +63,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue, Prop } from "vue-property-decorator";
|
import { Component, Vue, Prop } from "vue-property-decorator";
|
||||||
import { Route } from "vue-router";
|
import { Route } from "vue-router";
|
||||||
|
import { formatBytes } from "@/utils/datetime";
|
||||||
import { GET_USER, SUSPEND_USER } from "../../graphql/user";
|
import { GET_USER, SUSPEND_USER } from "../../graphql/user";
|
||||||
import { usernameWithDomain } from "../../types/actor/actor.model";
|
import { usernameWithDomain } from "../../types/actor/actor.model";
|
||||||
import RouteName from "../../router/name";
|
import RouteName from "../../router/name";
|
||||||
@ -139,11 +143,16 @@ export default class AdminUserProfile extends Vue {
|
|||||||
{
|
{
|
||||||
key: this.$i18n.t("Last IP adress"),
|
key: this.$i18n.t("Last IP adress"),
|
||||||
value: this.user.currentSignInIp || this.$t("Unknown"),
|
value: this.user.currentSignInIp || this.$t("Unknown"),
|
||||||
|
type: "code",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: this.$i18n.t("Participations"),
|
key: this.$i18n.t("Participations"),
|
||||||
value: this.user.participations.total,
|
value: this.user.participations.total,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: this.$i18n.t("Uploaded media size"),
|
||||||
|
value: formatBytes(this.user.mediaSize),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user