diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 2bcab87838..17e860aee4 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1080,10 +1080,10 @@ admin/views/index.vue: admin/views/dashboard.vue: dashboard: "ダッシュボード" - all-users: "全てのユーザー" - original-users: "このインスタンスのユーザー" - all-notes: "全ての投稿" - original-notes: "このインスタンスの投稿" + accounts: "アカウント" + notes: "投稿" + this-instance: "このインスタンス" + federated: "連合" invite: "招待" banner-url: "Banner URL" disableRegistration: "Disable new user registration" diff --git a/src/client/app/admin/views/cpu-memory.vue b/src/client/app/admin/views/cpu-memory.vue index 5d03b30ef4..00126325b1 100644 --- a/src/client/app/admin/views/cpu-memory.vue +++ b/src/client/app/admin/views/cpu-memory.vue @@ -1,79 +1,38 @@ <template> <div class="zyknedwtlthezamcjlolyusmipqmjgxz"> - <svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`"> - <defs> - <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 ref="cpu"></div> + <div ref="mem"></div> </div> </template> <script lang="ts"> import Vue from 'vue'; -import * as uuid from 'uuid'; +import * as ApexCharts from 'apexcharts'; export default Vue.extend({ props: ['connection'], + data() { return { - viewBoxX: 200, - viewBoxY: 70, stats: [], - cpuGradientId: uuid(), - cpuMaskId: uuid(), - memGradientId: uuid(), - memMaskId: uuid(), - cpuPolylinePoints: '', - memPolylinePoints: '', - cpuPolygonPoints: '', - memPolygonPoints: '', + cpuChart: null, + memChart: null, cpuP: '', 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() { this.connection.on('stats', this.onStats); this.connection.on('statsLog', this.onStatsLog); @@ -81,27 +40,75 @@ export default Vue.extend({ id: Math.random().toString().substr(2, 8), 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() { this.connection.off('stats', this.onStats); this.connection.off('statsLog', this.onStatsLog); }, + methods: { onStats(stats) { this.stats.push(stats); 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.memP = (stats.mem.used / stats.mem.total * 100).toFixed(0); }, + onStatsLog(statsLog) { statsLog.reverse().forEach(stats => this.onStats(stats)); } @@ -111,27 +118,17 @@ export default Vue.extend({ <style lang="stylus" scoped> .zyknedwtlthezamcjlolyusmipqmjgxz - > svg + display flex + + > div display block - width 50% - float left + flex 1 + padding 32px + box-shadow 0 2px 4px rgba(0, 0, 0, 0.1) + background var(--face) + border-radius 8px &:first-child - padding-right 5px - - &:last-child - padding-left 5px - - > text - font-size 10px - fill var(--chartCaption) - - > tspan - opacity 0.5 - - &:after - content "" - display block - clear both + margin-right 16px </style> diff --git a/src/client/app/admin/views/dashboard.vue b/src/client/app/admin/views/dashboard.vue index 5af5255e20..a48d184cf3 100644 --- a/src/client/app/admin/views/dashboard.vue +++ b/src/client/app/admin/views/dashboard.vue @@ -2,31 +2,51 @@ <div class="obdskegsannmntldydackcpzezagxqfy"> <div v-if="stats" class="stats"> <div> - <div>%fa:user%</div> <div> - <span>%i18n:@original-users%</span> - <b>{{ stats.originalUsersCount | number }}</b> + <div>%fa:user%</div> + <div> + <span>%i18n:@accounts%</span> + <b class="primary">{{ stats.originalUsersCount | number }}</b> + </div> + </div> + <div> + <span>%fa:home% %i18n:@this-instance%</span> </div> </div> <div> - <div>%fa:pencil-alt%</div> <div> - <span>%i18n:@original-notes%</span> - <b>{{ stats.originalNotesCount | number }}</b> + <div>%fa:pencil-alt%</div> + <div> + <span>%i18n:@notes%</span> + <b class="primary">{{ stats.originalNotesCount | number }}</b> + </div> + </div> + <div> + <span>%fa:home% %i18n:@this-instance%</span> </div> </div> <div> - <div>%fa:user%</div> <div> - <span>%i18n:@all-users%</span> - <b>{{ stats.usersCount | number }}</b> + <div>%fa:user%</div> + <div> + <span>%i18n:@accounts%</span> + <b>{{ stats.usersCount | number }}</b> + </div> + </div> + <div> + <span>%fa:globe% %i18n:@federated%</span> </div> </div> <div> - <div>%fa:pencil-alt%</div> <div> - <span>%i18n:@all-notes%</span> - <b>{{ stats.notesCount | number }}</b> + <div>%fa:pencil-alt%</div> + <div> + <span>%i18n:@notes%</span> + <b>{{ stats.notesCount | number }}</b> + </div> + </div> + <div> + <span>%fa:globe% %i18n:@federated%</span> </div> </div> </div> @@ -78,40 +98,53 @@ export default Vue.extend({ margin-bottom 16px > div - display flex - align-items center flex 1 max-width 300px margin-right 16px - text-align center color var(--text) box-shadow 0 2px 4px rgba(0, 0, 0, 0.1) background var(--face) border-radius 8px &:last-child - margin-right 0 + margin-right 0 > div:first-child - padding 16px 24px - font-size 28px + display flex + align-items center + text-align center + + &:last-child + margin-right 0 + + > div:first-child + padding 16px 24px + font-size 28px + + > div:last-child + flex 1 + padding 16px 32px 16px 0 + text-align right + + > span + font-size 70% + opacity 0.7 + + > b + display block + + &.primary + color var(--primary) > div:last-child - flex 1 - padding 16px 32px 16px 0 - text-align right + padding 6px 16px + border-top solid 1px #eee > span + font-size 70% opacity 0.7 - > b - display block - > .cpu-memory margin-bottom 16px - padding 32px - box-shadow 0 2px 4px rgba(0, 0, 0, 0.1) - background var(--face) - border-radius 8px </style>