diff options
| author | zyoshoka <107108195+zyoshoka@users.noreply.github.com> | 2024-01-12 15:29:06 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-12 15:29:06 +0900 |
| commit | 1aeede97f5d56ee4d98a2069de6d4aab7979a6e3 (patch) | |
| tree | 590733b31d2f196b30106d0e12a30c94475b1363 /packages/frontend/src/pages/user | |
| parent | enhance(drop-and-fusion): add new mode, some tweaks (diff) | |
| download | misskey-1aeede97f5d56ee4d98a2069de6d4aab7979a6e3.tar.gz misskey-1aeede97f5d56ee4d98a2069de6d4aab7979a6e3.tar.bz2 misskey-1aeede97f5d56ee4d98a2069de6d4aab7979a6e3.zip | |
refactor(frontend): `activity.heatmap.vue`をコンポーネントに置換 (#12967)
Diffstat (limited to 'packages/frontend/src/pages/user')
| -rw-r--r-- | packages/frontend/src/pages/user/activity.heatmap.vue | 219 | ||||
| -rw-r--r-- | packages/frontend/src/pages/user/activity.vue | 4 |
2 files changed, 2 insertions, 221 deletions
diff --git a/packages/frontend/src/pages/user/activity.heatmap.vue b/packages/frontend/src/pages/user/activity.heatmap.vue deleted file mode 100644 index ea3276a890..0000000000 --- a/packages/frontend/src/pages/user/activity.heatmap.vue +++ /dev/null @@ -1,219 +0,0 @@ -<!-- -SPDX-FileCopyrightText: syuilo and other misskey contributors -SPDX-License-Identifier: AGPL-3.0-only ---> - -<template> -<div ref="rootEl"> - <MkLoading v-if="fetching"/> - <div v-else :class="$style.root" class="_panel"> - <canvas ref="chartEl"></canvas> - </div> -</div> -</template> - -<script lang="ts" setup> -import { onMounted, nextTick, watch, shallowRef, ref } from 'vue'; -import { Chart } from 'chart.js'; -import * as Misskey from 'misskey-js'; -import { misskeyApi } from '@/scripts/misskey-api.js'; -import { defaultStore } from '@/store.js'; -import { useChartTooltip } from '@/scripts/use-chart-tooltip.js'; -import { alpha } from '@/scripts/color.js'; -import { initChart } from '@/scripts/init-chart.js'; - -initChart(); - -const props = defineProps<{ - src: string; - user: Misskey.entities.User; -}>(); - -const rootEl = shallowRef<HTMLDivElement>(null); -const chartEl = shallowRef<HTMLCanvasElement>(null); -const now = new Date(); -let chartInstance: Chart = null; -const fetching = ref(true); - -const { handler: externalTooltipHandler } = useChartTooltip({ - position: 'middle', -}); - -async function renderChart() { - if (chartInstance) { - chartInstance.destroy(); - } - - const wide = rootEl.value.offsetWidth > 700; - const narrow = rootEl.value.offsetWidth < 400; - - const weeks = wide ? 50 : narrow ? 10 : 25; - const chartLimit = 7 * weeks; - - 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) => { - const dt = getDate(i); - const iso = `${dt.getFullYear()}-${(dt.getMonth() + 1).toString().padStart(2, '0')}-${dt.getDate().toString().padStart(2, '0')}`; - return { - x: iso, - y: dt.getDay(), - d: iso, - v, - }; - }); - }; - - let values; - - if (props.src === 'notes') { - const raw = await misskeyApi('charts/user/notes', { userId: props.user.id, limit: chartLimit, span: 'day' }); - values = raw.inc; - } - - fetching.value = false; - - await nextTick(); - - const color = defaultStore.state.darkMode ? '#b4e900' : '#86b300'; - - // 視覚上の分かりやすさのため上から最も大きい3つの値の平均を最大値とする - const max = values.slice().sort((a, b) => b - a).slice(0, 3).reduce((a, b) => a + b, 0) / 3; - - const min = Math.max(0, Math.min(...values) - 1); - - const marginEachCell = 4; - - chartInstance = new Chart(chartEl.value, { - type: 'matrix', - data: { - datasets: [{ - label: '', - data: format(values), - pointRadius: 0, - borderWidth: 0, - borderJoinStyle: 'round', - borderRadius: 3, - backgroundColor(c) { - const value = c.dataset.data[c.dataIndex].v; - let a = (value - min) / max; - if (value !== 0) { // 0でない限りは完全に不可視にはしない - a = Math.max(a, 0.05); - } - return alpha(color, a); - }, - fill: true, - width(c) { - const a = c.chart.chartArea ?? {}; - return (a.right - a.left) / weeks - marginEachCell; - }, - height(c) { - const a = c.chart.chartArea ?? {}; - return (a.bottom - a.top) / 7 - marginEachCell; - }, - /* @see <https://github.com/misskey-dev/misskey/pull/10365#discussion_r1155511107> - }] satisfies ChartData[], - */ - }], - }, - options: { - aspectRatio: wide ? 6 : narrow ? 1.8 : 3.2, - layout: { - padding: { - left: 8, - right: 0, - top: 0, - bottom: 0, - }, - }, - scales: { - x: { - type: 'time', - offset: true, - position: 'bottom', - time: { - unit: 'week', - round: 'week', - isoWeekday: 0, - displayFormats: { - day: 'M/d', - month: 'Y/M', - week: 'M/d', - }, - }, - grid: { - display: false, - }, - ticks: { - display: true, - maxRotation: 0, - autoSkipPadding: 8, - }, - }, - y: { - offset: true, - reverse: true, - position: 'right', - grid: { - display: false, - }, - ticks: { - maxRotation: 0, - autoSkip: true, - padding: 1, - font: { - size: 9, - }, - callback: (value, index, values) => ['', 'Mon', '', 'Wed', '', 'Fri', ''][value], - }, - }, - }, - plugins: { - legend: { - display: false, - }, - tooltip: { - enabled: false, - callbacks: { - title(context) { - const v = context[0].dataset.data[context[0].dataIndex]; - return v.d; - }, - label(context) { - const v = context.dataset.data[context.dataIndex]; - return [v.v]; - }, - }, - //mode: 'index', - animation: { - duration: 0, - }, - external: externalTooltipHandler, - }, - }, - }, - }); -} - -watch(() => props.src, () => { - fetching.value = true; - renderChart(); -}); - -onMounted(async () => { - renderChart(); -}); -</script> - -<style lang="scss" module> -.root { - padding: 20px; -} -</style> diff --git a/packages/frontend/src/pages/user/activity.vue b/packages/frontend/src/pages/user/activity.vue index 6703890893..3c7635a312 100644 --- a/packages/frontend/src/pages/user/activity.vue +++ b/packages/frontend/src/pages/user/activity.vue @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only <div class="_gaps"> <MkFoldableSection class="item"> <template #header><i class="ti ti-activity"></i> Heatmap</template> - <XHeatmap :user="user" :src="'notes'"/> + <MkHeatmap :user="user" :src="'notes'"/> </MkFoldableSection> <MkFoldableSection class="item"> <template #header><i class="ti ti-pencil"></i> Notes</template> @@ -28,11 +28,11 @@ SPDX-License-Identifier: AGPL-3.0-only <script lang="ts" setup> import * as Misskey from 'misskey-js'; -import XHeatmap from './activity.heatmap.vue'; import XPv from './activity.pv.vue'; import XNotes from './activity.notes.vue'; import XFollowing from './activity.following.vue'; import MkFoldableSection from '@/components/MkFoldableSection.vue'; +import MkHeatmap from '@/components/MkHeatmap.vue'; const props = defineProps<{ user: Misskey.entities.User; |