From 4e4c559db6964cbf17fcadf38d55fc79c995ca42 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Fri, 22 Oct 2021 05:36:48 +0900
Subject: Migrate to Chart.js v3 (#7896)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* 定期的にresync

* Update overview.vue

* wip

* wip
---
 src/client/components/instance-stats.vue | 487 +------------------------------
 1 file changed, 15 insertions(+), 472 deletions(-)

(limited to 'src/client/components/instance-stats.vue')

diff --git a/src/client/components/instance-stats.vue b/src/client/components/instance-stats.vue
index 5e7c71ea65..fd0b75609f 100644
--- a/src/client/components/instance-stats.vue
+++ b/src/client/components/instance-stats.vue
@@ -24,35 +24,26 @@
 				<option value="drive-total">{{ $ts._charts.storageUsageTotal }}</option>
 			</optgroup>
 		</MkSelect>
-		<MkSelect v-model="chartSpan" style="margin: 0;">
+		<MkSelect v-model="chartSpan" style="margin: 0 0 0 10px;">
 			<option value="hour">{{ $ts.perHour }}</option>
 			<option value="day">{{ $ts.perDay }}</option>
 		</MkSelect>
 	</div>
-	<canvas ref="chart"></canvas>
+	<MkChart :src="chartSrc" :span="chartSpan" :limit="chartLimit" :detailed="detailed"></MkChart>
 </div>
 </template>
 
 <script lang="ts">
-import { defineComponent, markRaw } from 'vue';
-import Chart from 'chart.js';
-import MkSelect from './form/select.vue';
-import number from '@client/filters/number';
-
-const sum = (...arr) => arr.reduce((r, a) => r.map((b, i) => a[i] + b));
-const negate = arr => arr.map(x => -x);
-const alpha = (hex, a) => {
-	const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)!;
-	const r = parseInt(result[1], 16);
-	const g = parseInt(result[2], 16);
-	const b = parseInt(result[3], 16);
-	return `rgba(${r}, ${g}, ${b}, ${a})`;
-};
+import { defineComponent, onMounted, ref, watch } from 'vue';
+import MkSelect from '@client/components/form/select.vue';
+import MkChart from '@client/components/chart.vue';
 import * as os from '@client/os';
+import { defaultStore } from '@client/store';
 
 export default defineComponent({
 	components: {
-		MkSelect
+		MkSelect,
+		MkChart,
 	},
 
 	props: {
@@ -68,463 +59,15 @@ export default defineComponent({
 		},
 	},
 
-	data() {
-		return {
-			notesLocalWoW: 0,
-			notesLocalDoD: 0,
-			notesRemoteWoW: 0,
-			notesRemoteDoD: 0,
-			usersLocalWoW: 0,
-			usersLocalDoD: 0,
-			usersRemoteWoW: 0,
-			usersRemoteDoD: 0,
-			now: null,
-			chart: null,
-			chartInstance: null,
-			chartSrc: 'notes',
-			chartSpan: 'hour',
-		}
-	},
-
-	computed: {
-		data(): any {
-			if (this.chart == null) return null;
-			switch (this.chartSrc) {
-				case 'federation-instances': return this.federationInstancesChart(false);
-				case 'federation-instances-total': return this.federationInstancesChart(true);
-				case 'users': return this.usersChart(false);
-				case 'users-total': return this.usersChart(true);
-				case 'active-users': return this.activeUsersChart();
-				case 'notes': return this.notesChart('combined');
-				case 'local-notes': return this.notesChart('local');
-				case 'remote-notes': return this.notesChart('remote');
-				case 'notes-total': return this.notesTotalChart();
-				case 'drive': return this.driveChart();
-				case 'drive-total': return this.driveTotalChart();
-				case 'drive-files': return this.driveFilesChart();
-				case 'drive-files-total': return this.driveFilesTotalChart();
-			}
-		},
-
-		stats(): any[] {
-			const stats =
-				this.chartSpan == 'day' ? this.chart.perDay :
-				this.chartSpan == 'hour' ? this.chart.perHour :
-				null;
-
-			return stats;
-		}
-	},
-
-	watch: {
-		chartSrc() {
-			this.renderChart();
-		},
-
-		chartSpan() {
-			this.renderChart();
-		}
-	},
-
-	async created() {
-		this.now = new Date();
+	setup() {
+		const chartSpan = ref<'hour' | 'day'>('hour');
+		const chartSrc = ref('notes');
 
-		this.fetchChart();
+		return {
+			chartSrc,
+			chartSpan,
+		};
 	},
-
-	methods: {
-		async fetchChart() {
-			const [perHour, perDay] = await Promise.all([Promise.all([
-				os.api('charts/federation', { limit: this.chartLimit, span: 'hour' }),
-				os.api('charts/users', { limit: this.chartLimit, span: 'hour' }),
-				os.api('charts/active-users', { limit: this.chartLimit, span: 'hour' }),
-				os.api('charts/notes', { limit: this.chartLimit, span: 'hour' }),
-				os.api('charts/drive', { limit: this.chartLimit, span: 'hour' }),
-			]), Promise.all([
-				os.api('charts/federation', { limit: this.chartLimit, span: 'day' }),
-				os.api('charts/users', { limit: this.chartLimit, span: 'day' }),
-				os.api('charts/active-users', { limit: this.chartLimit, span: 'day' }),
-				os.api('charts/notes', { limit: this.chartLimit, span: 'day' }),
-				os.api('charts/drive', { limit: this.chartLimit, span: 'day' }),
-			])]);
-
-			const chart = {
-				perHour: {
-					federation: perHour[0],
-					users: perHour[1],
-					activeUsers: perHour[2],
-					notes: perHour[3],
-					drive: perHour[4],
-				},
-				perDay: {
-					federation: perDay[0],
-					users: perDay[1],
-					activeUsers: perDay[2],
-					notes: perDay[3],
-					drive: perDay[4],
-				}
-			};
-
-			this.chart = chart;
-
-			this.renderChart();
-		},
-
-		renderChart() {
-			if (this.chartInstance) {
-				this.chartInstance.destroy();
-			}
-
-			// TODO: var(--panel)の色が暗いか明るいかで判定する
-			const gridColor = this.$store.state.darkMode ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)';
-
-			Chart.defaults.global.defaultFontColor = getComputedStyle(document.documentElement).getPropertyValue('--fg');
-			this.chartInstance = markRaw(new Chart(this.$refs.chart, {
-				type: 'line',
-				data: {
-					labels: new Array(this.chartLimit).fill(0).map((_, i) => this.getDate(i).toLocaleString()).slice().reverse(),
-					datasets: this.data.series.map(x => ({
-						label: x.name,
-						data: x.data.slice().reverse(),
-						pointRadius: 0,
-						lineTension: 0,
-						borderWidth: 2,
-						borderColor: x.color,
-						borderDash: x.borderDash || [],
-						backgroundColor: alpha(x.color, 0.1),
-						fill: x.fill == null ? true : x.fill,
-						hidden: !!x.hidden
-					}))
-				},
-				options: {
-					aspectRatio: 2.5,
-					layout: {
-						padding: {
-							left: 16,
-							right: 16,
-							top: 16,
-							bottom: 8
-						}
-					},
-					legend: {
-						position: 'bottom',
-						labels: {
-							boxWidth: 16,
-						}
-					},
-					scales: {
-						xAxes: [{
-							type: 'time',
-							time: {
-								stepSize: 1,
-								unit: this.chartSpan == 'day' ? 'month' : 'day',
-							},
-							gridLines: {
-								display: this.detailed,
-								color: gridColor,
-								zeroLineColor: gridColor,
-							},
-							ticks: {
-								display: this.detailed
-							}
-						}],
-						yAxes: [{
-							position: 'left',
-							gridLines: {
-								color: gridColor,
-								zeroLineColor: gridColor,
-							},
-							ticks: {
-								display: this.detailed
-							}
-						}]
-					},
-					tooltips: {
-						intersect: false,
-						mode: 'index',
-					}
-				}
-			}));
-		},
-
-		getDate(ago: number) {
-			const y = this.now.getFullYear();
-			const m = this.now.getMonth();
-			const d = this.now.getDate();
-			const h = this.now.getHours();
-
-			return this.chartSpan == 'day' ? new Date(y, m, d - ago) : new Date(y, m, d, h - ago);
-		},
-
-		format(arr) {
-			const now = Date.now();
-			return arr.map((v, i) => ({
-				x: new Date(now - ((this.chartSpan == 'day' ? 86400000 :3600000 ) * i)),
-				y: v
-			}));
-		},
-
-		federationInstancesChart(total: boolean): any {
-			return {
-				series: [{
-					name: 'Instances',
-					color: '#008FFB',
-					data: this.format(total
-						? this.stats.federation.instance.total
-						: sum(this.stats.federation.instance.inc, negate(this.stats.federation.instance.dec))
-					)
-				}]
-			};
-		},
-
-		notesChart(type: string): any {
-			return {
-				series: [{
-					name: 'All',
-					type: 'line',
-					color: '#008FFB',
-					borderDash: [5, 5],
-					fill: false,
-					data: this.format(type == 'combined'
-						? sum(this.stats.notes.local.inc, negate(this.stats.notes.local.dec), this.stats.notes.remote.inc, negate(this.stats.notes.remote.dec))
-						: sum(this.stats.notes[type].inc, negate(this.stats.notes[type].dec))
-					)
-				}, {
-					name: 'Renotes',
-					type: 'area',
-					color: '#00E396',
-					data: this.format(type == 'combined'
-						? sum(this.stats.notes.local.diffs.renote, this.stats.notes.remote.diffs.renote)
-						: this.stats.notes[type].diffs.renote
-					)
-				}, {
-					name: 'Replies',
-					type: 'area',
-					color: '#FEB019',
-					data: this.format(type == 'combined'
-						? sum(this.stats.notes.local.diffs.reply, this.stats.notes.remote.diffs.reply)
-						: this.stats.notes[type].diffs.reply
-					)
-				}, {
-					name: 'Normal',
-					type: 'area',
-					color: '#FF4560',
-					data: this.format(type == 'combined'
-						? sum(this.stats.notes.local.diffs.normal, this.stats.notes.remote.diffs.normal)
-						: this.stats.notes[type].diffs.normal
-					)
-				}]
-			};
-		},
-
-		notesTotalChart(): any {
-			return {
-				series: [{
-					name: 'Combined',
-					type: 'line',
-					color: '#008FFB',
-					data: this.format(sum(this.stats.notes.local.total, this.stats.notes.remote.total))
-				}, {
-					name: 'Local',
-					type: 'area',
-					color: '#008FFB',
-					hidden: true,
-					data: this.format(this.stats.notes.local.total)
-				}, {
-					name: 'Remote',
-					type: 'area',
-					color: '#008FFB',
-					hidden: true,
-					data: this.format(this.stats.notes.remote.total)
-				}]
-			};
-		},
-
-		usersChart(total: boolean): any {
-			return {
-				series: [{
-					name: 'Combined',
-					type: 'line',
-					color: '#008FFB',
-					data: this.format(total
-						? sum(this.stats.users.local.total, this.stats.users.remote.total)
-						: sum(this.stats.users.local.inc, negate(this.stats.users.local.dec), this.stats.users.remote.inc, negate(this.stats.users.remote.dec))
-					)
-				}, {
-					name: 'Local',
-					type: 'area',
-					color: '#008FFB',
-					hidden: true,
-					data: this.format(total
-						? this.stats.users.local.total
-						: sum(this.stats.users.local.inc, negate(this.stats.users.local.dec))
-					)
-				}, {
-					name: 'Remote',
-					type: 'area',
-					color: '#008FFB',
-					hidden: true,
-					data: this.format(total
-						? this.stats.users.remote.total
-						: sum(this.stats.users.remote.inc, negate(this.stats.users.remote.dec))
-					)
-				}]
-			};
-		},
-
-		activeUsersChart(): any {
-			return {
-				series: [{
-					name: 'Combined',
-					type: 'line',
-					color: '#008FFB',
-					data: this.format(sum(this.stats.activeUsers.local.count, this.stats.activeUsers.remote.count))
-				}, {
-					name: 'Local',
-					type: 'area',
-					color: '#008FFB',
-					hidden: true,
-					data: this.format(this.stats.activeUsers.local.count)
-				}, {
-					name: 'Remote',
-					type: 'area',
-					color: '#008FFB',
-					hidden: true,
-					data: this.format(this.stats.activeUsers.remote.count)
-				}]
-			};
-		},
-
-		driveChart(): any {
-			return {
-				bytes: true,
-				series: [{
-					name: 'All',
-					type: 'line',
-					color: '#09d8e2',
-					borderDash: [5, 5],
-					fill: false,
-					data: this.format(
-						sum(
-							this.stats.drive.local.incSize,
-							negate(this.stats.drive.local.decSize),
-							this.stats.drive.remote.incSize,
-							negate(this.stats.drive.remote.decSize)
-						)
-					)
-				}, {
-					name: 'Local +',
-					type: 'area',
-					color: '#008FFB',
-					data: this.format(this.stats.drive.local.incSize)
-				}, {
-					name: 'Local -',
-					type: 'area',
-					color: '#FF4560',
-					data: this.format(negate(this.stats.drive.local.decSize))
-				}, {
-					name: 'Remote +',
-					type: 'area',
-					color: '#00E396',
-					data: this.format(this.stats.drive.remote.incSize)
-				}, {
-					name: 'Remote -',
-					type: 'area',
-					color: '#FEB019',
-					data: this.format(negate(this.stats.drive.remote.decSize))
-				}]
-			};
-		},
-
-		driveTotalChart(): any {
-			return {
-				bytes: true,
-				series: [{
-					name: 'Combined',
-					type: 'line',
-					color: '#008FFB',
-					data: this.format(sum(this.stats.drive.local.totalSize, this.stats.drive.remote.totalSize))
-				}, {
-					name: 'Local',
-					type: 'area',
-					color: '#008FFB',
-					hidden: true,
-					data: this.format(this.stats.drive.local.totalSize)
-				}, {
-					name: 'Remote',
-					type: 'area',
-					color: '#008FFB',
-					hidden: true,
-					data: this.format(this.stats.drive.remote.totalSize)
-				}]
-			};
-		},
-
-		driveFilesChart(): any {
-			return {
-				series: [{
-					name: 'All',
-					type: 'line',
-					color: '#09d8e2',
-					borderDash: [5, 5],
-					fill: false,
-					data: this.format(
-						sum(
-							this.stats.drive.local.incCount,
-							negate(this.stats.drive.local.decCount),
-							this.stats.drive.remote.incCount,
-							negate(this.stats.drive.remote.decCount)
-						)
-					)
-				}, {
-					name: 'Local +',
-					type: 'area',
-					color: '#008FFB',
-					data: this.format(this.stats.drive.local.incCount)
-				}, {
-					name: 'Local -',
-					type: 'area',
-					color: '#FF4560',
-					data: this.format(negate(this.stats.drive.local.decCount))
-				}, {
-					name: 'Remote +',
-					type: 'area',
-					color: '#00E396',
-					data: this.format(this.stats.drive.remote.incCount)
-				}, {
-					name: 'Remote -',
-					type: 'area',
-					color: '#FEB019',
-					data: this.format(negate(this.stats.drive.remote.decCount))
-				}]
-			};
-		},
-
-		driveFilesTotalChart(): any {
-			return {
-				series: [{
-					name: 'Combined',
-					type: 'line',
-					color: '#008FFB',
-					data: this.format(sum(this.stats.drive.local.totalCount, this.stats.drive.remote.totalCount))
-				}, {
-					name: 'Local',
-					type: 'area',
-					color: '#008FFB',
-					hidden: true,
-					data: this.format(this.stats.drive.local.totalCount)
-				}, {
-					name: 'Remote',
-					type: 'area',
-					color: '#008FFB',
-					hidden: true,
-					data: this.format(this.stats.drive.remote.totalCount)
-				}]
-			};
-		},
-
-		number
-	}
 });
 </script>
 
-- 
cgit v1.2.3-freya

