feat(client): add tag cloud component

This commit is contained in:
syuilo 2022-06-29 21:22:15 +09:00
parent f997b7dff2
commit c9b3ab80ca
3 changed files with 133 additions and 1 deletions

21
packages/client/assets/tagcanvas.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View 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>

View file

@ -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;
}
}
} }
} }