diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2023-04-22 12:50:40 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2023-04-22 12:50:40 +0900 |
| commit | d437e148db668c298e24a226d7bb1791d89b65e8 (patch) | |
| tree | 389e39609f7639bb0df6e45cbc2b68fa06cb1728 /packages/frontend/src/components | |
| parent | :art: (diff) | |
| download | misskey-d437e148db668c298e24a226d7bb1791d89b65e8.tar.gz misskey-d437e148db668c298e24a226d7bb1791d89b65e8.tar.bz2 misskey-d437e148db668c298e24a226d7bb1791d89b65e8.zip | |
:art:
Diffstat (limited to 'packages/frontend/src/components')
| -rw-r--r-- | packages/frontend/src/components/MkVisitorDashboard.ActiveUsersChart.vue | 157 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkVisitorDashboard.vue | 29 |
2 files changed, 173 insertions, 13 deletions
diff --git a/packages/frontend/src/components/MkVisitorDashboard.ActiveUsersChart.vue b/packages/frontend/src/components/MkVisitorDashboard.ActiveUsersChart.vue new file mode 100644 index 0000000000..fb705786cf --- /dev/null +++ b/packages/frontend/src/components/MkVisitorDashboard.ActiveUsersChart.vue @@ -0,0 +1,157 @@ +<template> +<div> + <MkLoading v-if="fetching"/> + <div v-show="!fetching" :class="$style.root"> + <canvas ref="chartEl"></canvas> + </div> +</div> +</template> + +<script lang="ts" setup> +import { onMounted } from 'vue'; +import { Chart } from 'chart.js'; +import gradient from 'chartjs-plugin-gradient'; +import tinycolor from 'tinycolor2'; +import * as os from '@/os'; +import { defaultStore } from '@/store'; +import { useChartTooltip } from '@/scripts/use-chart-tooltip'; +import { chartVLine } from '@/scripts/chart-vline'; +import { initChart } from '@/scripts/init-chart'; + +initChart(); + +const chartEl = $shallowRef<HTMLCanvasElement>(null); +const now = new Date(); +let chartInstance: Chart = null; +const chartLimit = 30; +let fetching = $ref(true); + +const { handler: externalTooltipHandler } = useChartTooltip(); + +async function renderChart() { + if (chartInstance) { + chartInstance.destroy(); + } + + const getDate = (ago: number) => { + const y = now.getFullYear(); + const m = now.getMonth(); + const d = now.getDate(); + + return new Date(y, m, d - ago); + }; + + const format = (arr) => { + return arr.map((v, i) => ({ + x: getDate(i).getTime(), + y: v, + })); + }; + + const raw = await os.api('charts/active-users', { limit: chartLimit, span: 'day' }); + + const vLineColor = defaultStore.state.darkMode ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)'; + + const computedStyle = getComputedStyle(document.documentElement); + const accent = tinycolor(computedStyle.getPropertyValue('--accent')).toHexString(); + + const colorRead = accent; + const colorWrite = '#2ecc71'; + + const max = Math.max(...raw.read); + + chartInstance = new Chart(chartEl, { + type: 'bar', + data: { + datasets: [{ + parsing: false, + label: 'Read', + data: format(raw.read).slice().reverse(), + pointRadius: 0, + borderWidth: 0, + borderJoinStyle: 'round', + borderRadius: 4, + backgroundColor: colorRead, + barPercentage: 0.5, + categoryPercentage: 1, + fill: true, + }], + }, + options: { + aspectRatio: 2.5, + layout: { + padding: { + left: 0, + right: 8, + top: 0, + bottom: 0, + }, + }, + scales: { + x: { + type: 'time', + offset: true, + time: { + stepSize: 1, + unit: 'day', + displayFormats: { + day: 'M/d', + month: 'Y/M', + }, + }, + grid: { + display: false, + }, + ticks: { + display: true, + maxRotation: 0, + autoSkipPadding: 8, + }, + }, + y: { + position: 'left', + suggestedMax: 10, + grid: { + display: true, + }, + ticks: { + display: true, + //mirror: true, + }, + }, + }, + interaction: { + intersect: false, + mode: 'index', + }, + plugins: { + legend: { + display: false, + }, + tooltip: { + enabled: false, + mode: 'index', + animation: { + duration: 0, + }, + external: externalTooltipHandler, + }, + gradient, + }, + }, + plugins: [chartVLine(vLineColor)], + }); + + fetching = false; +} + +onMounted(async () => { + renderChart(); +}); +</script> + +<style lang="scss" module> +.root { + padding: 20px; +} +</style> diff --git a/packages/frontend/src/components/MkVisitorDashboard.vue b/packages/frontend/src/components/MkVisitorDashboard.vue index 80717a2618..9de5200ef0 100644 --- a/packages/frontend/src/components/MkVisitorDashboard.vue +++ b/packages/frontend/src/components/MkVisitorDashboard.vue @@ -1,6 +1,6 @@ <template> <div v-if="meta" :class="$style.root"> - <div :class="$style.main"> + <div :class="[$style.main, $style.panel]"> <img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.mainIcon"/> <button class="_button _acrylic" :class="$style.mainMenu" @click="showMenu"><i class="ti ti-dots"></i></button> <div :class="$style.mainFg"> @@ -24,21 +24,24 @@ </div> </div> <div v-if="stats" :class="$style.stats"> - <div :class="$style.statsItem"> + <div :class="[$style.statsItem, $style.panel]"> <div :class="$style.statsItemLabel">{{ i18n.ts.users }}</div> <div :class="$style.statsItemCount"><MkNumber :value="stats.originalUsersCount"/></div> </div> - <div :class="$style.statsItem"> + <div :class="[$style.statsItem, $style.panel]"> <div :class="$style.statsItemLabel">{{ i18n.ts.notes }}</div> <div :class="$style.statsItemCount"><MkNumber :value="stats.originalNotesCount"/></div> </div> </div> - <div v-if="instance.policies.ltlAvailable" :class="$style.tl"> + <div v-if="instance.policies.ltlAvailable" :class="[$style.tl, $style.panel]"> <div :class="$style.tlHeader">{{ i18n.ts.letsLookAtTimeline }}</div> <div :class="$style.tlBody"> <MkTimeline src="local"/> </div> </div> + <div :class="[$style.activeUsersChart, $style.panel]"> + <XActiveUsersChart/> + </div> </div> </template> @@ -57,6 +60,7 @@ import { i18n } from '@/i18n'; import { instance } from '@/instance'; import number from '@/filters/number'; import MkNumber from '@/components/MkNumber.vue'; +import XActiveUsersChart from '@/components/MkVisitorDashboard.ActiveUsersChart.vue'; let meta = $ref<Instance>(); let stats = $ref(null); @@ -119,11 +123,14 @@ function exploreOtherServers() { padding: 32px 0 0 0; } -.main { +.panel { position: relative; background: var(--panel); border-radius: var(--radius); box-shadow: 0 12px 32px rgb(0 0 0 / 25%); +} + +.main { text-align: center; } @@ -185,11 +192,7 @@ function exploreOtherServers() { } .statsItem { - position: relative; - background: var(--panel); - border-radius: var(--radius); overflow: clip; - box-shadow: 0 12px 32px rgb(0 0 0 / 25%); padding: 16px 20px; } @@ -205,11 +208,7 @@ function exploreOtherServers() { } .tl { - position: relative; - background: var(--panel); - border-radius: var(--radius); overflow: clip; - box-shadow: 0 12px 32px rgb(0 0 0 / 25%); } .tlHeader { @@ -221,4 +220,8 @@ function exploreOtherServers() { height: 350px; overflow: auto; } + +.activeUsersChart { + +} </style> |