improve heatmap
This commit is contained in:
		
							parent
							
								
									78a8e918a0
								
							
						
					
					
						commit
						3968597a7b
					
				
					 3 changed files with 61 additions and 18 deletions
				
			
		|  | @ -8,7 +8,7 @@ | |||
| </template> | ||||
| 
 | ||||
| <script lang="ts" setup> | ||||
| import { markRaw, version as vueVersion, onMounted, onBeforeUnmount, nextTick } from 'vue'; | ||||
| import { markRaw, version as vueVersion, onMounted, onBeforeUnmount, nextTick, watch } from 'vue'; | ||||
| import { | ||||
| 	Chart, | ||||
| 	ArcElement, | ||||
|  | @ -54,6 +54,10 @@ Chart.register( | |||
| 	MatrixController, MatrixElement, | ||||
| ); | ||||
| 
 | ||||
| const props = defineProps<{ | ||||
| 	src: string; | ||||
| }>(); | ||||
| 
 | ||||
| const rootEl = $ref<HTMLDivElement>(null); | ||||
| const chartEl = $ref<HTMLCanvasElement>(null); | ||||
| const now = new Date(); | ||||
|  | @ -96,7 +100,24 @@ async function renderChart() { | |||
| 		}); | ||||
| 	}; | ||||
| 
 | ||||
| 	const raw = await os.api('charts/active-users', { limit: chartLimit, span: 'day' }); | ||||
| 	let values; | ||||
| 
 | ||||
| 	if (props.src === 'active-users') { | ||||
| 		const raw = await os.api('charts/active-users', { limit: chartLimit, span: 'day' }); | ||||
| 		values = raw.readWrite; | ||||
| 	} else if (props.src === 'notes') { | ||||
| 		const raw = await os.api('charts/notes', { limit: chartLimit, span: 'day' }); | ||||
| 		values = raw.local.inc; | ||||
| 	} else if (props.src === 'ap-requests-inbox-received') { | ||||
| 		const raw = await os.api('charts/ap-request', { limit: chartLimit, span: 'day' }); | ||||
| 		values = raw.inboxReceived; | ||||
| 	} else if (props.src === 'ap-requests-deliver-succeeded') { | ||||
| 		const raw = await os.api('charts/ap-request', { limit: chartLimit, span: 'day' }); | ||||
| 		values = raw.deliverSucceeded; | ||||
| 	} else if (props.src === 'ap-requests-deliver-failed') { | ||||
| 		const raw = await os.api('charts/ap-request', { limit: chartLimit, span: 'day' }); | ||||
| 		values = raw.deliverFailed; | ||||
| 	} | ||||
| 
 | ||||
| 	fetching = false; | ||||
| 
 | ||||
|  | @ -110,7 +131,9 @@ async function renderChart() { | |||
| 	const color = defaultStore.state.darkMode ? '#b4e900' : '#86b300'; | ||||
| 
 | ||||
| 	// 視覚上の分かりやすさのため上から最も大きい3つの値の平均を最大値とする | ||||
| 	const max = raw.readWrite.slice().sort((a, b) => b - a).slice(0, 3).reduce((a, b) => a + b, 0) / 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; | ||||
| 
 | ||||
|  | @ -119,14 +142,17 @@ async function renderChart() { | |||
| 		data: { | ||||
| 			datasets: [{ | ||||
| 				label: 'Read & Write', | ||||
| 				data: format(raw.readWrite), | ||||
| 				data: format(values), | ||||
| 				pointRadius: 0, | ||||
| 				borderWidth: 0, | ||||
| 				borderJoinStyle: 'round', | ||||
| 				borderRadius: 3, | ||||
| 				backgroundColor(c) { | ||||
| 					const value = c.dataset.data[c.dataIndex].v; | ||||
| 					const a = value / max; | ||||
| 					let a = (value - min) / max; | ||||
| 					if (value !== 0) { // 0でない限りは完全に不可視にはしない | ||||
| 						a = Math.max(a, 0.05); | ||||
| 					} | ||||
| 					return alpha(color, a); | ||||
| 				}, | ||||
| 				fill: true, | ||||
|  | @ -222,6 +248,11 @@ async function renderChart() { | |||
| 	}); | ||||
| } | ||||
| 
 | ||||
| watch(() => props.src, () => { | ||||
| 	fetching = true; | ||||
| 	renderChart(); | ||||
| }); | ||||
| 
 | ||||
| onMounted(async () => { | ||||
| 	renderChart(); | ||||
| }); | ||||
|  | @ -38,8 +38,15 @@ | |||
| 
 | ||||
| 	<MkFolder class="item"> | ||||
| 		<template #header>Active users heatmap</template> | ||||
| 		<MkSelect v-model="heatmapSrc" style="margin: 0 0 12px 0;"> | ||||
| 			<option value="active-users">Active users</option> | ||||
| 			<option value="notes">Notes</option> | ||||
| 			<option value="ap-requests-inbox-received">AP Requests: inboxReceived</option> | ||||
| 			<option value="ap-requests-deliver-succeeded">AP Requests: deliverSucceeded</option> | ||||
| 			<option value="ap-requests-deliver-failed">AP Requests: deliverFailed</option> | ||||
| 		</MkSelect> | ||||
| 		<div class="_panel" :class="$style.heatmap"> | ||||
| 			<MkActiveUsersHeatmap/> | ||||
| 			<MkHeatmap :src="heatmapSrc"/> | ||||
| 		</div> | ||||
| 	</MkFolder> | ||||
| 
 | ||||
|  | @ -93,7 +100,7 @@ import MkChart from '@/components/MkChart.vue'; | |||
| import { useChartTooltip } from '@/scripts/use-chart-tooltip'; | ||||
| import * as os from '@/os'; | ||||
| import { i18n } from '@/i18n'; | ||||
| import MkActiveUsersHeatmap from '@/components/MkActiveUsersHeatmap.vue'; | ||||
| import MkHeatmap from '@/components/MkHeatmap.vue'; | ||||
| import MkFolder from '@/components/MkFolder.vue'; | ||||
| import MkRetentionHeatmap from '@/components/MkRetentionHeatmap.vue'; | ||||
| 
 | ||||
|  | @ -115,15 +122,10 @@ Chart.register( | |||
| 	Filler, | ||||
| ); | ||||
| 
 | ||||
| const props = withDefaults(defineProps<{ | ||||
| 	chartLimit?: number; | ||||
| 	detailed?: boolean; | ||||
| }>(), { | ||||
| 	chartLimit: 90, | ||||
| }); | ||||
| 
 | ||||
| const chartSpan = $ref<'hour' | 'day'>('hour'); | ||||
| const chartSrc = $ref('active-users'); | ||||
| const chartLimit = 90; | ||||
| let chartSpan = $ref<'hour' | 'day'>('hour'); | ||||
| let chartSrc = $ref('active-users'); | ||||
| let heatmapSrc = $ref('active-users'); | ||||
| let subDoughnutEl = $ref<HTMLCanvasElement>(); | ||||
| let pubDoughnutEl = $ref<HTMLCanvasElement>(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,11 +1,21 @@ | |||
| <template> | ||||
| <div class="_panel" :class="$style.root"> | ||||
| 	<MkActiveUsersHeatmap/> | ||||
| 	<MkSelect v-model="src" style="margin: 0 0 12px 0;" small> | ||||
| 		<option value="active-users">Active users</option> | ||||
| 		<option value="notes">Notes</option> | ||||
| 		<option value="ap-requests-inbox-received">AP Requests: inboxReceived</option> | ||||
| 		<option value="ap-requests-deliver-succeeded">AP Requests: deliverSucceeded</option> | ||||
| 		<option value="ap-requests-deliver-failed">AP Requests: deliverFailed</option> | ||||
| 	</MkSelect> | ||||
| 	<MkHeatmap :src="src"/> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts" setup> | ||||
| import MkActiveUsersHeatmap from '@/components/MkActiveUsersHeatmap.vue'; | ||||
| import MkHeatmap from '@/components/MkHeatmap.vue'; | ||||
| import MkSelect from '@/components/form/select.vue'; | ||||
| 
 | ||||
| let src = $ref('active-users'); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" module> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue