summaryrefslogtreecommitdiff
path: root/packages/client/src
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2022-06-29 21:22:15 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2022-06-29 21:22:15 +0900
commitc9b3ab80ca9f1bfa6815fa73c5d885f1c1caa0b5 (patch)
tree57aee4b0dcbd0f7164c402cd79efdec8a6a969cd /packages/client/src
parentchore(client): fix type def (diff)
downloadsharkey-c9b3ab80ca9f1bfa6815fa73c5d885f1c1caa0b5.tar.gz
sharkey-c9b3ab80ca9f1bfa6815fa73c5d885f1c1caa0b5.tar.bz2
sharkey-c9b3ab80ca9f1bfa6815fa73c5d885f1c1caa0b5.zip
feat(client): add tag cloud component
Diffstat (limited to 'packages/client/src')
-rw-r--r--packages/client/src/components/tag-cloud.vue80
-rw-r--r--packages/client/src/pages/admin/overview.vue33
2 files changed, 112 insertions, 1 deletions
diff --git a/packages/client/src/components/tag-cloud.vue b/packages/client/src/components/tag-cloud.vue
new file mode 100644
index 0000000000..43ab49357b
--- /dev/null
+++ b/packages/client/src/components/tag-cloud.vue
@@ -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>
diff --git a/packages/client/src/pages/admin/overview.vue b/packages/client/src/pages/admin/overview.vue
index 190f756f78..6ccee8aea2 100644
--- a/packages/client/src/pages/admin/overview.vue
+++ b/packages/client/src/pages/admin/overview.vue
@@ -108,6 +108,17 @@
</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 class="body">
<div class="chart deliver">
@@ -154,8 +165,8 @@ import XFederation from './overview.federation.vue';
import XQueueChart from './overview.queue-chart.vue';
import XUser from './overview.user.vue';
import XPie from './overview.pie.vue';
-import MkInstanceStats from '@/components/instance-stats.vue';
import MkNumberDiff from '@/components/number-diff.vue';
+import MkTagCloud from '@/components/tag-cloud.vue';
import { version, url } from '@/config';
import number from '@/filters/number';
import * as os from '@/os';
@@ -197,6 +208,7 @@ let federationPubActiveDiff = $ref<number | null>(null);
let federationSubActive = $ref<number | null>(null);
let federationSubActiveDiff = $ref<number | null>(null);
let newUsers = $ref(null);
+let activeInstances = $shallowRef(null);
const queueStatsConnection = markRaw(stream.useChannel('queueStats'));
const now = new Date();
let chartInstance: Chart = null;
@@ -363,6 +375,10 @@ async function renderChart() {
});
}
+function onInstanceClick(i) {
+ os.pageWindow(`/instance-info/${i.host}`);
+}
+
onMounted(async () => {
/*
const magicGrid = new MagicGrid({
@@ -410,6 +426,13 @@ onMounted(async () => {
newUsers = res;
});
+ os.api('federation/instances', {
+ sort: '+lastCommunicatedAt',
+ limit: 25,
+ }).then(res => {
+ activeInstances = res;
+ });
+
nextTick(() => {
queueStatsConnection.send('requestLog', {
id: Math.random().toString().substr(2, 8),
@@ -577,6 +600,14 @@ definePageMetadata({
}
}
}
+
+ &.tagCloud {
+ > .body {
+ background: var(--panel);
+ border-radius: var(--radius);
+ overflow: clip;
+ }
+ }
}
}