mirror of
https://github.com/misskey-dev/misskey.git
synced 2024-12-11 21:30:51 +01:00
enhance(client): tweak control panel dashboard
This commit is contained in:
parent
f071ea4902
commit
6a4574b612
4 changed files with 158 additions and 13 deletions
|
@ -2,14 +2,14 @@
|
||||||
<div class="wbrkwale">
|
<div class="wbrkwale">
|
||||||
<MkLoading v-if="fetching"/>
|
<MkLoading v-if="fetching"/>
|
||||||
<transition-group v-else tag="div" :name="$store.state.animation ? 'chart' : ''" class="instances">
|
<transition-group v-else tag="div" :name="$store.state.animation ? 'chart' : ''" class="instances">
|
||||||
<div v-for="(instance, i) in instances" :key="instance.id" class="instance">
|
<MkA v-for="(instance, i) in instances" :key="instance.id" :to="`/instance-info/${instance.host}`" class="instance">
|
||||||
<img v-if="instance.iconUrl" :src="instance.iconUrl" alt=""/>
|
<img v-if="instance.iconUrl" :src="instance.iconUrl" alt=""/>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<a class="a" :href="'https://' + instance.host" target="_blank" :title="instance.host">{{ instance.name ?? instance.host }}</a>
|
<div class="name">{{ instance.name ?? instance.host }}</div>
|
||||||
<p>{{ instance.host }}</p>
|
<div class="host">{{ instance.host }}</div>
|
||||||
</div>
|
</div>
|
||||||
<MkMiniChart class="chart" :src="charts[i].requests.received"/>
|
<MkMiniChart class="chart" :src="charts[i].requests.received"/>
|
||||||
</div>
|
</MkA>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -78,7 +78,7 @@ onUnmounted(() => {
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
|
|
||||||
> .a {
|
> .name {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
@ -86,7 +86,7 @@ onUnmounted(() => {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
> p {
|
> .host {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 75%;
|
font-size: 75%;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
|
|
@ -146,7 +146,7 @@ onMounted(() => {
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
aspectRatio: 2.5,
|
aspectRatio: 3,
|
||||||
layout: {
|
layout: {
|
||||||
padding: {
|
padding: {
|
||||||
left: 0,
|
left: 0,
|
||||||
|
|
76
packages/client/src/pages/admin/overview.user.vue
Normal file
76
packages/client/src/pages/admin/overview.user.vue
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<template>
|
||||||
|
<MkA :class="[$style.root]" :to="`/user-info/${user.id}`">
|
||||||
|
<MkAvatar class="avatar" :user="user" :disable-link="true" :show-indicator="true"/>
|
||||||
|
<div class="body">
|
||||||
|
<span class="name"><MkUserName class="name" :user="user"/></span>
|
||||||
|
<span class="sub"><span class="acct _monospace">@{{ acct(user) }}</span></span>
|
||||||
|
</div>
|
||||||
|
<MkMiniChart v-if="chart" class="chart" :src="chart.inc"/>
|
||||||
|
</MkA>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import * as misskey from 'misskey-js';
|
||||||
|
import MkMiniChart from '@/components/mini-chart.vue';
|
||||||
|
import * as os from '@/os';
|
||||||
|
import { acct } from '@/filters/user';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
user: misskey.entities.User;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const chart = $ref(null);
|
||||||
|
|
||||||
|
os.apiGet('charts/user/notes', { userId: props.user.id, limit: 16, span: 'day' }).then(res => {
|
||||||
|
chart = res;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" module>
|
||||||
|
.root {
|
||||||
|
$bodyTitleHieght: 18px;
|
||||||
|
$bodyInfoHieght: 16px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
> :global(.avatar) {
|
||||||
|
display: block;
|
||||||
|
width: ($bodyTitleHieght + $bodyInfoHieght);
|
||||||
|
height: ($bodyTitleHieght + $bodyInfoHieght);
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> :global(.body) {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: var(--fg);
|
||||||
|
padding-right: 8px;
|
||||||
|
|
||||||
|
> :global(.name) {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
line-height: $bodyTitleHieght;
|
||||||
|
}
|
||||||
|
|
||||||
|
> :global(.sub) {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 95%;
|
||||||
|
opacity: 0.7;
|
||||||
|
line-height: $bodyInfoHieght;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> :global(.chart) {
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -34,6 +34,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="container users">
|
||||||
|
<div class="title">New users</div>
|
||||||
|
<div v-if="newUsers" class="body">
|
||||||
|
<XUser v-for="user in newUsers" :key="user.id" class="user" :user="user"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!--<XMetrics/>-->
|
<!--<XMetrics/>-->
|
||||||
|
|
||||||
<div class="container env">
|
<div class="container env">
|
||||||
|
@ -75,6 +82,30 @@
|
||||||
<XFederation/>
|
<XFederation/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="stats" class="container federationStats">
|
||||||
|
<div class="title">Federation</div>
|
||||||
|
<div class="body">
|
||||||
|
<div class="number _panel">
|
||||||
|
<div class="label">Sub</div>
|
||||||
|
<div class="value _monospace">
|
||||||
|
{{ number(federationSubActive) }}
|
||||||
|
<MkNumberDiff v-tooltip="i18n.ts.dayOverDayChanges" class="diff" :value="federationSubActiveDiff"><template #before>(</template><template #after>)</template></MkNumberDiff>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="number _panel">
|
||||||
|
<div class="label">Pub</div>
|
||||||
|
<div class="value _monospace">
|
||||||
|
{{ number(federationPubActive) }}
|
||||||
|
<MkNumberDiff v-tooltip="i18n.ts.dayOverDayChanges" class="diff" :value="federationPubActiveDiff"><template #before>(</template><template #after>)</template></MkNumberDiff>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container files">
|
||||||
|
<div class="title">Recent files</div>
|
||||||
|
<div class="body">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</MkSpacer>
|
</MkSpacer>
|
||||||
|
@ -105,6 +136,7 @@ import MagicGrid from 'magic-grid';
|
||||||
import XMetrics from './metrics.vue';
|
import XMetrics from './metrics.vue';
|
||||||
import XFederation from './overview.federation.vue';
|
import XFederation from './overview.federation.vue';
|
||||||
import XQueueChart from './overview.queue-chart.vue';
|
import XQueueChart from './overview.queue-chart.vue';
|
||||||
|
import XUser from './overview.user.vue';
|
||||||
import MkInstanceStats from '@/components/instance-stats.vue';
|
import MkInstanceStats from '@/components/instance-stats.vue';
|
||||||
import MkNumberDiff from '@/components/number-diff.vue';
|
import MkNumberDiff from '@/components/number-diff.vue';
|
||||||
import { version, url } from '@/config';
|
import { version, url } from '@/config';
|
||||||
|
@ -141,6 +173,11 @@ let stats: any = $ref(null);
|
||||||
let serverInfo: any = $ref(null);
|
let serverInfo: any = $ref(null);
|
||||||
let usersComparedToThePrevDay: any = $ref(null);
|
let usersComparedToThePrevDay: any = $ref(null);
|
||||||
let notesComparedToThePrevDay: any = $ref(null);
|
let notesComparedToThePrevDay: any = $ref(null);
|
||||||
|
let federationPubActive = $ref<number | null>(null);
|
||||||
|
let federationPubActiveDiff = $ref<number | null>(null);
|
||||||
|
let federationSubActive = $ref<number | null>(null);
|
||||||
|
let federationSubActiveDiff = $ref<number | null>(null);
|
||||||
|
let newUsers = $ref(null);
|
||||||
const queueStatsConnection = markRaw(stream.useChannel('queueStats'));
|
const queueStatsConnection = markRaw(stream.useChannel('queueStats'));
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
let chartInstance: Chart = null;
|
let chartInstance: Chart = null;
|
||||||
|
@ -325,10 +362,24 @@ onMounted(async () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
os.apiGet('charts/federation', { limit: 2, span: 'day' }).then(chart => {
|
||||||
|
federationPubActive = chart.pubActive[0];
|
||||||
|
federationPubActiveDiff = chart.pubActive[0] - chart.pubActive[1];
|
||||||
|
federationSubActive = chart.subActive[0];
|
||||||
|
federationSubActiveDiff = chart.subActive[0] - chart.subActive[1];
|
||||||
|
});
|
||||||
|
|
||||||
os.api('admin/server-info').then(serverInfoResponse => {
|
os.api('admin/server-info').then(serverInfoResponse => {
|
||||||
serverInfo = serverInfoResponse;
|
serverInfo = serverInfoResponse;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
os.api('admin/show-users', {
|
||||||
|
limit: 5,
|
||||||
|
sort: '+createdAt',
|
||||||
|
}).then(res => {
|
||||||
|
newUsers = res;
|
||||||
|
});
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
queueStatsConnection.send('requestLog', {
|
queueStatsConnection.send('requestLog', {
|
||||||
id: Math.random().toString().substr(2, 8),
|
id: Math.random().toString().substr(2, 8),
|
||||||
|
@ -364,12 +415,12 @@ definePageMetadata({
|
||||||
margin: 32px 0;
|
margin: 32px 0;
|
||||||
|
|
||||||
> .title {
|
> .title {
|
||||||
font-size: 1.2em;
|
font-size: 1.1em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.stats {
|
&.stats, &.federationStats {
|
||||||
> .body {
|
> .body {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-gap: 16px;
|
grid-gap: 16px;
|
||||||
|
@ -388,7 +439,7 @@ definePageMetadata({
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
|
|
||||||
> .diff {
|
> .diff {
|
||||||
font-size: 0.8em;
|
font-size: 0.7em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -410,7 +461,7 @@ definePageMetadata({
|
||||||
}
|
}
|
||||||
|
|
||||||
> .value {
|
> .value {
|
||||||
font-size: 1.2em;
|
font-size: 1.1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -424,6 +475,21 @@ definePageMetadata({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.users {
|
||||||
|
> .body {
|
||||||
|
background: var(--panel);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
|
||||||
|
> .user {
|
||||||
|
padding: 16px 20px;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
border-bottom: solid 0.5px var(--divider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.federation {
|
&.federation {
|
||||||
> .body {
|
> .body {
|
||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
|
@ -434,7 +500,8 @@ definePageMetadata({
|
||||||
|
|
||||||
&.queue {
|
&.queue {
|
||||||
> .body {
|
> .body {
|
||||||
padding: 32px;
|
position: relative;
|
||||||
|
padding: 24px;
|
||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
|
|
||||||
|
@ -443,7 +510,9 @@ definePageMetadata({
|
||||||
}
|
}
|
||||||
|
|
||||||
> .title {
|
> .title {
|
||||||
|
position: absolute;
|
||||||
|
top: 24px;
|
||||||
|
left: 24px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue