feat(client): add tag cloud component
This commit is contained in:
		
							parent
							
								
									f997b7dff2
								
							
						
					
					
						commit
						c9b3ab80ca
					
				
					 3 changed files with 133 additions and 1 deletions
				
			
		
							
								
								
									
										21
									
								
								packages/client/assets/tagcanvas.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								packages/client/assets/tagcanvas.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										80
									
								
								packages/client/src/components/tag-cloud.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								packages/client/src/components/tag-cloud.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,80 @@ | ||||||
|  | <template> | ||||||
|  | <div class="root"> | ||||||
|  | 	<canvas :id="idForCanvas" ref="canvasEl" class="canvas" width="300" height="300"></canvas> | ||||||
|  | 	<div :id="idForTags" ref="tagsEl" class="tags"> | ||||||
|  | 		<ul> | ||||||
|  | 			<slot></slot> | ||||||
|  | 		</ul> | ||||||
|  | 	</div> | ||||||
|  | </div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script lang="ts" setup> | ||||||
|  | import { onMounted, ref, watch, PropType, onBeforeUnmount } from 'vue'; | ||||||
|  | import tinycolor from 'tinycolor2'; | ||||||
|  | 
 | ||||||
|  | const props = defineProps<{}>(); | ||||||
|  | 
 | ||||||
|  | const loaded = !!window.TagCanvas; | ||||||
|  | const SAFE_FOR_HTML_ID = 'abcdefghijklmnopqrstuvwxyz'; | ||||||
|  | const computedStyle = getComputedStyle(document.documentElement); | ||||||
|  | const idForCanvas = Array.from(Array(16)).map(() => SAFE_FOR_HTML_ID[Math.floor(Math.random() * SAFE_FOR_HTML_ID.length)]).join(''); | ||||||
|  | const idForTags = Array.from(Array(16)).map(() => SAFE_FOR_HTML_ID[Math.floor(Math.random() * SAFE_FOR_HTML_ID.length)]).join(''); | ||||||
|  | let available = $ref(false); | ||||||
|  | let canvasEl = $ref<HTMLCanvasElement | null>(null); | ||||||
|  | let tagsEl = $ref<HTMLElement | null>(null); | ||||||
|  | 
 | ||||||
|  | watch($$(available), () => { | ||||||
|  | 	window.TagCanvas.Start(idForCanvas, idForTags, { | ||||||
|  | 		textColour: '#ffffff', | ||||||
|  | 		outlineColour: tinycolor(computedStyle.getPropertyValue('--accent')).toHexString(), | ||||||
|  | 		outlineRadius: 10, | ||||||
|  | 		initial: [-0.030, -0.010], | ||||||
|  | 		frontSelect: true, | ||||||
|  | 		imageRadius: 8, | ||||||
|  | 		//dragControl: true, | ||||||
|  | 		dragThreshold: 3, | ||||||
|  | 		wheelZoom: false, | ||||||
|  | 		reverse: true, | ||||||
|  | 		depth: 0.5, | ||||||
|  | 		maxSpeed: 0.2, | ||||||
|  | 		minSpeed: 0.003, | ||||||
|  | 		stretchX: 0.8, | ||||||
|  | 		stretchY: 0.8, | ||||||
|  | 	}); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | onMounted(() => { | ||||||
|  | 	if (loaded) { | ||||||
|  | 		available = true; | ||||||
|  | 	} else { | ||||||
|  | 		document.head.appendChild(Object.assign(document.createElement('script'), { | ||||||
|  | 			async: true, | ||||||
|  | 			src: '/client-assets/tagcanvas.min.js', | ||||||
|  | 		})).addEventListener('load', () => available = true); | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | onBeforeUnmount(() => { | ||||||
|  | 	window.TagCanvas.Delete(idForCanvas); | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | .root { | ||||||
|  | 	position: relative; | ||||||
|  | 	overflow: clip; | ||||||
|  | 	display: grid; | ||||||
|  | 	place-items: center; | ||||||
|  | 
 | ||||||
|  | 	> .canvas { | ||||||
|  | 		display: block; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	> .tags { | ||||||
|  | 		position: absolute; | ||||||
|  | 		top: 999px; | ||||||
|  | 		left: 999px; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | @ -108,6 +108,17 @@ | ||||||
| 					</div> | 					</div> | ||||||
| 				</div> | 				</div> | ||||||
| 			</div> | 			</div> | ||||||
|  | 			<div class="container tagCloud"> | ||||||
|  | 				<div class="body"> | ||||||
|  | 					<MkTagCloud v-if="activeInstances"> | ||||||
|  | 						<li v-for="instance in activeInstances"> | ||||||
|  | 							<a @click.prevent="onInstanceClick(instance)"> | ||||||
|  | 								<img style="width: 32px;" :src="instance.iconUrl"> | ||||||
|  | 							</a> | ||||||
|  | 						</li> | ||||||
|  | 					</MkTagCloud> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
| 			<div v-if="fedStats" class="container federationPies"> | 			<div v-if="fedStats" class="container federationPies"> | ||||||
| 				<div class="body"> | 				<div class="body"> | ||||||
| 					<div class="chart deliver"> | 					<div class="chart deliver"> | ||||||
|  | @ -154,8 +165,8 @@ import XFederation from './overview.federation.vue'; | ||||||
| import XQueueChart from './overview.queue-chart.vue'; | import XQueueChart from './overview.queue-chart.vue'; | ||||||
| import XUser from './overview.user.vue'; | import XUser from './overview.user.vue'; | ||||||
| import XPie from './overview.pie.vue'; | import XPie from './overview.pie.vue'; | ||||||
| import MkInstanceStats from '@/components/instance-stats.vue'; |  | ||||||
| import MkNumberDiff from '@/components/number-diff.vue'; | import MkNumberDiff from '@/components/number-diff.vue'; | ||||||
|  | import MkTagCloud from '@/components/tag-cloud.vue'; | ||||||
| import { version, url } from '@/config'; | import { version, url } from '@/config'; | ||||||
| import number from '@/filters/number'; | import number from '@/filters/number'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
|  | @ -197,6 +208,7 @@ let federationPubActiveDiff = $ref<number | null>(null); | ||||||
| let federationSubActive = $ref<number | null>(null); | let federationSubActive = $ref<number | null>(null); | ||||||
| let federationSubActiveDiff = $ref<number | null>(null); | let federationSubActiveDiff = $ref<number | null>(null); | ||||||
| let newUsers = $ref(null); | let newUsers = $ref(null); | ||||||
|  | let activeInstances = $shallowRef(null); | ||||||
| const queueStatsConnection = markRaw(stream.useChannel('queueStats')); | const queueStatsConnection = markRaw(stream.useChannel('queueStats')); | ||||||
| const now = new Date(); | const now = new Date(); | ||||||
| let chartInstance: Chart = null; | let chartInstance: Chart = null; | ||||||
|  | @ -363,6 +375,10 @@ async function renderChart() { | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | function onInstanceClick(i) { | ||||||
|  | 	os.pageWindow(`/instance-info/${i.host}`); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| onMounted(async () => { | onMounted(async () => { | ||||||
| 	/* | 	/* | ||||||
| 	const magicGrid = new MagicGrid({ | 	const magicGrid = new MagicGrid({ | ||||||
|  | @ -410,6 +426,13 @@ onMounted(async () => { | ||||||
| 		newUsers = res; | 		newUsers = res; | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
|  | 	os.api('federation/instances', { | ||||||
|  | 		sort: '+lastCommunicatedAt', | ||||||
|  | 		limit: 25, | ||||||
|  | 	}).then(res => { | ||||||
|  | 		activeInstances = res; | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
| 	nextTick(() => { | 	nextTick(() => { | ||||||
| 		queueStatsConnection.send('requestLog', { | 		queueStatsConnection.send('requestLog', { | ||||||
| 			id: Math.random().toString().substr(2, 8), | 			id: Math.random().toString().substr(2, 8), | ||||||
|  | @ -577,6 +600,14 @@ definePageMetadata({ | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
|  | 			&.tagCloud { | ||||||
|  | 				> .body { | ||||||
|  | 					background: var(--panel); | ||||||
|  | 					border-radius: var(--radius); | ||||||
|  | 					overflow: clip; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue