mirror of
https://github.com/kokonect-link/cherrypick
synced 2025-01-19 00:03:19 +09:00
feat(client): 新しいサーバーメトリクスウィジェットの追加
This commit is contained in:
parent
74dbe60ccf
commit
c8d0cecabd
@ -53,6 +53,7 @@
|
||||
- 헤더에 뒤로 가기 버튼 추가
|
||||
- 업데이트 팝업 개선 (Misskey와 CherryPick의 변경 사항을 직관적으로 볼 수 있도록)
|
||||
- 서버 통계 위젯의 원 그래프 디자인 개선
|
||||
- 새로운 서버 통계 위젯 추가
|
||||
- Fix: (Friendly) 위젯 영역에 safe-area-inset-bottom이 적용되지 않음
|
||||
- Fix: (Friendly) 플로팅 메뉴를 길게 눌렀을 때 프로필 이미지를 드래그 할 수 있는 문제
|
||||
- Fix: 위젯 편집 시 헤더 이외의 영역을 눌렀을 때 위젯 설정이 뜨는 문제
|
||||
|
69
packages/frontend/src/widgets/server-metric/cpu-mem-pie.vue
Normal file
69
packages/frontend/src/widgets/server-metric/cpu-mem-pie.vue
Normal file
@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div :class="$style.root">
|
||||
<XPie :class="$style.pie" :value="cpuUsage"/>
|
||||
<div :class="$style.div">
|
||||
<p>CPU</p>
|
||||
<text x="50%" y="50%" dy="0.05" text-anchor="middle" :class="$style.text">{{ (cpuUsage * 100).toFixed(1) }}<span style="font-weight: normal; font-size: .75em; margin-left: 2px;">%</span></text>
|
||||
</div>
|
||||
<XPie :class="$style.pie" :value="memUsage"/>
|
||||
<div :class="$style.div">
|
||||
<p>RAM</p>
|
||||
<text x="50%" y="50%" dy="0.05" text-anchor="middle" :class="$style.text">{{ (memUsage * 100).toFixed(1) }}<span style="font-weight: normal; font-size: .75em; margin-left: 2px;">%</span></text>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onBeforeUnmount } from 'vue';
|
||||
import XPie from './pie-compact.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
connection: any,
|
||||
meta: any,
|
||||
value: number
|
||||
}>();
|
||||
|
||||
let cpuUsage: number = $ref(0);
|
||||
let memUsage: number = $ref(0);
|
||||
|
||||
function onStats(stats) {
|
||||
cpuUsage = stats.cpu;
|
||||
memUsage = stats.mem.active / props.meta.mem.total;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
props.connection.on('stats', onStats);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
props.connection.off('stats', onStats);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
display: flex;
|
||||
padding: 16px 32px;
|
||||
}
|
||||
|
||||
.pie {
|
||||
height: 42px;
|
||||
flex-shrink: 0;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.div {
|
||||
flex: 1;
|
||||
margin: auto;
|
||||
|
||||
> p {
|
||||
margin: 0 0 2px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
font-weight: bold;
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
@ -6,10 +6,11 @@
|
||||
|
||||
<div v-if="meta" data-cy-mkw-serverMetric class="mkw-serverMetric">
|
||||
<XCpuMemory v-if="widgetProps.view === 0" :connection="connection" :meta="meta"/>
|
||||
<XNet v-else-if="widgetProps.view === 1" :connection="connection" :meta="meta"/>
|
||||
<XCpu v-else-if="widgetProps.view === 2" :connection="connection" :meta="meta"/>
|
||||
<XMemory v-else-if="widgetProps.view === 3" :connection="connection" :meta="meta"/>
|
||||
<XDisk v-else-if="widgetProps.view === 4" :connection="connection" :meta="meta"/>
|
||||
<XCpuMemoryCompact v-if="widgetProps.view === 1" :connection="connection" :meta="meta"/>
|
||||
<XNet v-else-if="widgetProps.view === 2" :connection="connection" :meta="meta"/>
|
||||
<XCpu v-else-if="widgetProps.view === 3" :connection="connection" :meta="meta"/>
|
||||
<XMemory v-else-if="widgetProps.view === 4" :connection="connection" :meta="meta"/>
|
||||
<XDisk v-else-if="widgetProps.view === 5" :connection="connection" :meta="meta"/>
|
||||
</div>
|
||||
</MkContainer>
|
||||
</template>
|
||||
@ -18,6 +19,7 @@
|
||||
import { onUnmounted, ref } from 'vue';
|
||||
import { useWidgetPropsManager, Widget, WidgetComponentExpose } from '../widget';
|
||||
import XCpuMemory from './cpu-mem.vue';
|
||||
import XCpuMemoryCompact from './cpu-mem-pie.vue';
|
||||
import XNet from './net.vue';
|
||||
import XCpu from './cpu.vue';
|
||||
import XMemory from './mem.vue';
|
||||
@ -67,7 +69,7 @@ os.api('server-info', {}).then(res => {
|
||||
});
|
||||
|
||||
const toggleView = () => {
|
||||
if (widgetProps.view === 4) {
|
||||
if (widgetProps.view === 5) {
|
||||
widgetProps.view = 0;
|
||||
} else {
|
||||
widgetProps.view++;
|
||||
|
49
packages/frontend/src/widgets/server-metric/pie-compact.vue
Normal file
49
packages/frontend/src/widgets/server-metric/pie-compact.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<svg :class="$style.root" viewBox="0 0 1 1" preserveAspectRatio="none">
|
||||
<circle
|
||||
:r="r"
|
||||
cx="50%" cy="50%"
|
||||
fill="none"
|
||||
stroke-width="0.2"
|
||||
stroke="rgba(0, 0, 0, 0.05)"
|
||||
:class="$style.circle"
|
||||
/>
|
||||
<circle
|
||||
:r="r"
|
||||
cx="50%" cy="50%"
|
||||
:stroke-dasharray="Math.PI * (r * 2)"
|
||||
:stroke-dashoffset="strokeDashoffset"
|
||||
fill="none"
|
||||
stroke-width="0.2"
|
||||
:class="$style.circle"
|
||||
:stroke="color"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { } from 'vue';
|
||||
|
||||
const props = defineProps<{
|
||||
value: number;
|
||||
}>();
|
||||
|
||||
const r = 0.35;
|
||||
|
||||
const color = $computed(() => `hsl(${180 - (props.value * 180)}, 80%, 70%)`);
|
||||
const strokeDashoffset = $computed(() => (1 - props.value) * (Math.PI * (r * 2)));
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
display: block;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.circle {
|
||||
transform-origin: center;
|
||||
transform: rotate(-90deg);
|
||||
transition: stroke-dashoffset 0.5s ease;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user