This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
Zaimki/routes/admin.vue

153 lines
6.0 KiB
Vue
Raw Normal View History

2020-10-29 15:41:40 -07:00
<template>
<NotFound v-if="!$admin()"/>
2020-11-16 11:43:44 -08:00
<div v-else>
2020-10-29 15:41:40 -07:00
<h2>
<Icon v="user-cog"/>
<T>admin.header</T>
</h2>
2020-11-24 16:11:17 -08:00
<section>
<details class="border mb-3">
<summary class="bg-light p-3">
<Icon v="users"/>
Users
({{stats.users.overall}}, {{stats.users.admins}} admins)
</summary>
<div class="border-top">
<Table :data="Object.values(users)" :columns="4">
<template v-slot:header>
<th class="text-nowrap">
<T>admin.user.user</T>
</th>
<th class="text-nowrap">
<T>admin.user.email</T>
</th>
<th class="text-nowrap">
<T>admin.user.roles</T>
</th>
<th class="text-nowrap">
<T>admin.user.profiles</T>
</th>
</template>
2020-10-29 15:41:40 -07:00
2020-11-24 16:11:17 -08:00
<template v-slot:row="s">
<td>
<Avatar :user="s.el" dsize="2rem"/>
{{s.el.username}}
</td>
<td>
<p>
<a :href="`mailto:${s.el.email}`" target="_blank" rel="noopener">
{{s.el.email}}
</a>
</p>
<ul v-if="s.el.socialConnections.length" class="list-inline">
<li v-for="conn in s.el.socialConnections" class="list-inline-item">
<Icon :v="socialProviders[conn].icon || conn" set="b"/>
</li>
</ul>
</td>
<td>
<a href="#" :class="['badge', s.el.roles === 'admin' ? 'badge-primary' : 'badge-light']"
@click.prevent="setRole(s.el.id, s.el.roles === 'admin' ? 'user' : 'admin')">
{{s.el.roles}}
</a>
</td>
<td>
<ul class="list-unstyled">
<li v-for="locale in s.el.profiles" v-if="locales[locale]">
<LocaleLink :link="`/@${s.el.username}`" :locale="locale">
{{ locales[locale].name }}
</LocaleLink>
</li>
</ul>
</td>
</template>
</Table>
</div>
</details>
</section>
<section v-for="(locale, k) in stats.locales" :key="k">
<details class="border mb-3" open>
<summary class="bg-light p-3">
<LocaleLink :locale="k" link="/">{{locale.name}}</LocaleLink>
</summary>
<div class="p-3 border-top d-flex justify-content-between flex-column flex-md-row">
<div class="flex-grow-1">
<h4 class="h5">
<Icon v="id-card"/>
Profiles
</h4>
{{locale.profiles}}
</div>
<div class="flex-grow-1">
<h4 class="h5">
<Icon v="tags"/>
Pronouns
</h4>
<ul class="list-unstyled">
<li v-for="(count, pronoun) in locale.pronouns" v-if="count >= 10">
<strong>{{pronoun}}</strong>: {{count}}
</li>
</ul>
</div>
<div class="flex-grow-1">
<h4 class="h5">
<Icon v="atom-alt"/>
Dictionary
</h4>
<ul class="list-unstyled">
<li>
<strong>Approved</strong>: {{locale.nouns.approved}}
</li>
<li>
<strong>Awaiting</strong>: {{locale.nouns.awaiting}}
</li>
</ul>
</div>
</div>
</details>
</section>
2020-10-29 15:41:40 -07:00
</div>
</template>
<script>
import {head} from "../src/helpers";
2020-11-02 12:45:45 -08:00
import {socialProviders} from "../src/data";
2020-10-29 15:41:40 -07:00
export default {
2020-11-02 12:45:45 -08:00
data() {
return { socialProviders }
},
2020-10-29 15:41:40 -07:00
async asyncData({ app, store }) {
if (!store.state.user || store.state.user.roles !== 'admin') {
return {};
}
2020-11-24 16:11:17 -08:00
const stats = await app.$axios.$get(`/admin/stats`);
const users = await app.$axios.$get(`/admin/users`);
2020-10-29 15:41:40 -07:00
return {
2020-11-24 16:11:17 -08:00
stats,
2020-11-03 01:03:07 -08:00
users,
2020-10-29 15:41:40 -07:00
};
},
2020-11-03 01:03:07 -08:00
methods: {
async setRole(userId, role) {
await this.$confirm(this.$t('admin.user.confirmRole', {username: this.users[userId].username, role}));
const response = await this.$axios.$post(`/user/${userId}/set-roles`, { roles: role });
this.users[userId].roles = role;
}
},
2020-10-29 15:41:40 -07:00
head() {
return head({
title: this.$t('admin.header'),
});
},
}
</script>