Improve admin page

This commit is contained in:
syuilo 2018-11-03 02:06:34 +09:00
parent 8ae94c034d
commit 6f1e2f6636
No known key found for this signature in database
GPG key ID: BDC4C49D06AB9D69
3 changed files with 148 additions and 118 deletions

View file

@ -1080,10 +1080,10 @@ admin/views/index.vue:
admin/views/dashboard.vue: admin/views/dashboard.vue:
dashboard: "ダッシュボード" dashboard: "ダッシュボード"
all-users: "全てのユーザー" accounts: "アカウント"
original-users: "このインスタンスのユーザー" notes: "投稿"
all-notes: "全ての投稿" this-instance: "このインスタンス"
original-notes: "このインスタンスの投稿" federated: "連合"
invite: "招待" invite: "招待"
banner-url: "Banner URL" banner-url: "Banner URL"
disableRegistration: "Disable new user registration" disableRegistration: "Disable new user registration"

View file

@ -1,79 +1,38 @@
<template> <template>
<div class="zyknedwtlthezamcjlolyusmipqmjgxz"> <div class="zyknedwtlthezamcjlolyusmipqmjgxz">
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`"> <div ref="cpu"></div>
<defs> <div ref="mem"></div>
<linearGradient :id="cpuGradientId" x1="0" x2="0" y1="1" y2="0">
<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
</linearGradient>
<mask :id="cpuMaskId" x="0" y="0" :width="viewBoxX" :height="viewBoxY">
<polygon
:points="cpuPolygonPoints"
fill="#fff"
fill-opacity="0.5"/>
<polyline
:points="cpuPolylinePoints"
fill="none"
stroke="#fff"
stroke-width="1"/>
</mask>
</defs>
<rect
x="0" y="0"
:width="viewBoxX" :height="viewBoxY"
:style="`stroke: none; fill: url(#${ cpuGradientId }); mask: url(#${ cpuMaskId })`"/>
<text x="1" y="12">CPU <tspan>{{ cpuP }}%</tspan></text>
</svg>
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
<defs>
<linearGradient :id="memGradientId" x1="0" x2="0" y1="1" y2="0">
<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
</linearGradient>
<mask :id="memMaskId" x="0" y="0" :width="viewBoxX" :height="viewBoxY">
<polygon
:points="memPolygonPoints"
fill="#fff"
fill-opacity="0.5"/>
<polyline
:points="memPolylinePoints"
fill="none"
stroke="#fff"
stroke-width="1"/>
</mask>
</defs>
<rect
x="0" y="0"
:width="viewBoxX" :height="viewBoxY"
:style="`stroke: none; fill: url(#${ memGradientId }); mask: url(#${ memMaskId })`"/>
<text x="1" y="12">MEM <tspan>{{ memP }}%</tspan></text>
</svg>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import * as uuid from 'uuid'; import * as ApexCharts from 'apexcharts';
export default Vue.extend({ export default Vue.extend({
props: ['connection'], props: ['connection'],
data() { data() {
return { return {
viewBoxX: 200,
viewBoxY: 70,
stats: [], stats: [],
cpuGradientId: uuid(), cpuChart: null,
cpuMaskId: uuid(), memChart: null,
memGradientId: uuid(),
memMaskId: uuid(),
cpuPolylinePoints: '',
memPolylinePoints: '',
cpuPolygonPoints: '',
memPolygonPoints: '',
cpuP: '', cpuP: '',
memP: '' memP: ''
}; };
}, },
watch: {
stats(stats) {
this.cpuChart.updateSeries([{
data: stats.map((x, i) => ({ x: i, y: x.cpu_usage }))
}]);
this.memChart.updateSeries([{
data: stats.map((x, i) => ({ x: i, y: (x.mem.used / x.mem.total) }))
}]);
}
},
mounted() { mounted() {
this.connection.on('stats', this.onStats); this.connection.on('stats', this.onStats);
this.connection.on('statsLog', this.onStatsLog); this.connection.on('statsLog', this.onStatsLog);
@ -81,27 +40,75 @@ export default Vue.extend({
id: Math.random().toString().substr(2, 8), id: Math.random().toString().substr(2, 8),
length: 200 length: 200
}); });
const chartOpts = {
chart: {
type: 'area',
height: 300,
animations: {
dynamicAnimation: {
enabled: false
}
}, },
toolbar: {
show: false
}
},
dataLabels: {
enabled: false
},
grid: {
clipMarkers: false,
},
stroke: {
curve: 'straight',
width: 2
},
series: [{
data: []
}],
xaxis: {
type: 'numeric',
labels: {
show: false
}
},
yaxis: {
show: false,
min: 0,
max: 1
}
};
this.cpuChart = new ApexCharts(this.$refs.cpu, Object.assign({}, chartOpts, {
title: {
text: 'CPU'
}
}));
this.memChart = new ApexCharts(this.$refs.mem, Object.assign({}, chartOpts, {
title: {
text: 'MEM'
}
}));
this.cpuChart.render();
this.memChart.render();
},
beforeDestroy() { beforeDestroy() {
this.connection.off('stats', this.onStats); this.connection.off('stats', this.onStats);
this.connection.off('statsLog', this.onStatsLog); this.connection.off('statsLog', this.onStatsLog);
}, },
methods: { methods: {
onStats(stats) { onStats(stats) {
this.stats.push(stats); this.stats.push(stats);
if (this.stats.length > 200) this.stats.shift(); if (this.stats.length > 200) this.stats.shift();
const cpuPolylinePoints = this.stats.map((s, i) => [this.viewBoxX - ((this.stats.length - 1) - i), (1 - s.cpu_usage) * this.viewBoxY]);
const memPolylinePoints = this.stats.map((s, i) => [this.viewBoxX - ((this.stats.length - 1) - i), (1 - (s.mem.used / s.mem.total)) * this.viewBoxY]);
this.cpuPolylinePoints = cpuPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' ');
this.memPolylinePoints = memPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' ');
this.cpuPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${this.viewBoxY} ${this.cpuPolylinePoints} ${this.viewBoxX},${this.viewBoxY}`;
this.memPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${this.viewBoxY} ${this.memPolylinePoints} ${this.viewBoxX},${this.viewBoxY}`;
this.cpuP = (stats.cpu_usage * 100).toFixed(0); this.cpuP = (stats.cpu_usage * 100).toFixed(0);
this.memP = (stats.mem.used / stats.mem.total * 100).toFixed(0); this.memP = (stats.mem.used / stats.mem.total * 100).toFixed(0);
}, },
onStatsLog(statsLog) { onStatsLog(statsLog) {
statsLog.reverse().forEach(stats => this.onStats(stats)); statsLog.reverse().forEach(stats => this.onStats(stats));
} }
@ -111,27 +118,17 @@ export default Vue.extend({
<style lang="stylus" scoped> <style lang="stylus" scoped>
.zyknedwtlthezamcjlolyusmipqmjgxz .zyknedwtlthezamcjlolyusmipqmjgxz
> svg display flex
> div
display block display block
width 50% flex 1
float left padding 32px
box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
background var(--face)
border-radius 8px
&:first-child &:first-child
padding-right 5px margin-right 16px
&:last-child
padding-left 5px
> text
font-size 10px
fill var(--chartCaption)
> tspan
opacity 0.5
&:after
content ""
display block
clear both
</style> </style>

View file

@ -1,34 +1,54 @@
<template> <template>
<div class="obdskegsannmntldydackcpzezagxqfy"> <div class="obdskegsannmntldydackcpzezagxqfy">
<div v-if="stats" class="stats"> <div v-if="stats" class="stats">
<div>
<div> <div>
<div>%fa:user%</div> <div>%fa:user%</div>
<div> <div>
<span>%i18n:@original-users%</span> <span>%i18n:@accounts%</span>
<b>{{ stats.originalUsersCount | number }}</b> <b class="primary">{{ stats.originalUsersCount | number }}</b>
</div> </div>
</div> </div>
<div>
<span>%fa:home% %i18n:@this-instance%</span>
</div>
</div>
<div>
<div> <div>
<div>%fa:pencil-alt%</div> <div>%fa:pencil-alt%</div>
<div> <div>
<span>%i18n:@original-notes%</span> <span>%i18n:@notes%</span>
<b>{{ stats.originalNotesCount | number }}</b> <b class="primary">{{ stats.originalNotesCount | number }}</b>
</div> </div>
</div> </div>
<div>
<span>%fa:home% %i18n:@this-instance%</span>
</div>
</div>
<div>
<div> <div>
<div>%fa:user%</div> <div>%fa:user%</div>
<div> <div>
<span>%i18n:@all-users%</span> <span>%i18n:@accounts%</span>
<b>{{ stats.usersCount | number }}</b> <b>{{ stats.usersCount | number }}</b>
</div> </div>
</div> </div>
<div>
<span>%fa:globe% %i18n:@federated%</span>
</div>
</div>
<div>
<div> <div>
<div>%fa:pencil-alt%</div> <div>%fa:pencil-alt%</div>
<div> <div>
<span>%i18n:@all-notes%</span> <span>%i18n:@notes%</span>
<b>{{ stats.notesCount | number }}</b> <b>{{ stats.notesCount | number }}</b>
</div> </div>
</div> </div>
<div>
<span>%fa:globe% %i18n:@federated%</span>
</div>
</div>
</div> </div>
<div class="cpu-memory"> <div class="cpu-memory">
@ -78,17 +98,22 @@ export default Vue.extend({
margin-bottom 16px margin-bottom 16px
> div > div
display flex
align-items center
flex 1 flex 1
max-width 300px max-width 300px
margin-right 16px margin-right 16px
text-align center
color var(--text) color var(--text)
box-shadow 0 2px 4px rgba(0, 0, 0, 0.1) box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
background var(--face) background var(--face)
border-radius 8px border-radius 8px
&:last-child
margin-right 0
> div:first-child
display flex
align-items center
text-align center
&:last-child &:last-child
margin-right 0 margin-right 0
@ -102,16 +127,24 @@ export default Vue.extend({
text-align right text-align right
> span > span
font-size 70%
opacity 0.7 opacity 0.7
> b > b
display block display block
&.primary
color var(--primary)
> div:last-child
padding 6px 16px
border-top solid 1px #eee
> span
font-size 70%
opacity 0.7
> .cpu-memory > .cpu-memory
margin-bottom 16px margin-bottom 16px
padding 32px
box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
background var(--face)
border-radius 8px
</style> </style>