Skip to content

Commit

Permalink
fix some issue on dashboard
Browse files Browse the repository at this point in the history
and prepare to specific daily report time
  • Loading branch information
zyxkad committed Mar 22, 2024
1 parent f3ac552 commit fae98aa
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 49 deletions.
6 changes: 5 additions & 1 deletion dashboard/src/assets/lang/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@
"when.disabled": "Notify when disabled",
"when.enabled": "Notify when enabled",
"when.sync.done": "Notify when sync finished",
"when.update.available": "Notify when updates available"
"when.update.available": "Notify when updates available",
"report": {
"daily": "Report daily requests",
"at": "Report at"
}
}
},
"message": {
Expand Down
6 changes: 5 additions & 1 deletion dashboard/src/assets/lang/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@
"when.disabled": "下线时发送通知",
"when.enabled": "上线时发送通知",
"when.sync.done": "同步完成时发送通知",
"when.update.available": "有更新时发送通知"
"when.update.available": "有更新时发送通知",
"report": {
"daily": "报告每日请求",
"at": "报告时间"
}
}
},
"message": {
Expand Down
2 changes: 1 addition & 1 deletion dashboard/src/components/LogBlock.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function activeScroller(): void {
}
scrolling = true
const MIN_SCROLL_SPEED = 100 // 100px per second
const MIN_SCROLL_SPEED = 500 // 500px per second
registerAnimationFrame((dt: number): boolean => {
if (!focusLastLog || !scrollYTarget || document.hidden || !box.value) {
scrolling = false
Expand Down
21 changes: 16 additions & 5 deletions dashboard/src/lang/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { type Ref, ref, watch } from 'vue'
import { Lang } from './lang'
export * from './lang'
import EN_US_JSON from '@/assets/lang/en-US.json'
import ZH_CN_JSON from '@/assets/lang/zh-CN.json'

// keys use with window.localStorage
const HAS_LOCAL_STORAGE = 'localStorage' in globalThis
const TR_LANG_CACHE_KEY = 'go-openbmclapi.dashboard.tr.lang'
const TR_DATA_CACHE_KEY = 'go-openbmclapi.dashboard.tr.map'

Expand All @@ -16,15 +19,19 @@ interface langItem {
}

export const avaliableLangs = [
{ code: new Lang('en-US'), tr: () => import('@/assets/lang/en-US.json') },
{ code: new Lang('zh-CN'), tr: () => import('@/assets/lang/zh-CN.json') },
{ code: new Lang('en-US'), tr: () => EN_US_JSON },
{ code: new Lang('zh-CN'), tr: () => ZH_CN_JSON },
// { code: new Lang('zh-CN'), tr: () => import('@/assets/lang/zh-CN.json') },
]

export const defaultLang = avaliableLangs[0]
const currentLang = ref(defaultLang)
const currentTr: Ref<LangMap | null> = ref(null)

;(async function () {
if (!HAS_LOCAL_STORAGE) {
return
}
const langCache = localStorage.getItem(TR_LANG_CACHE_KEY)
if (langCache) {
for (let a of avaliableLangs) {
Expand Down Expand Up @@ -53,11 +60,15 @@ export function getLang(): Lang {
export function setLang(lang: Lang | string): Lang | null {
for (let a of avaliableLangs) {
if (a.code.match(lang)) {
localStorage.setItem(TR_LANG_CACHE_KEY, a.code.toString())
if (HAS_LOCAL_STORAGE) {
localStorage.setItem(TR_LANG_CACHE_KEY, a.code.toString())
}
currentLang.value = a
a.tr().then((map) => {
Promise.resolve(a.tr()).then((map) => {
currentTr.value = map
localStorage.setItem(TR_DATA_CACHE_KEY, JSON.stringify(map))
if (HAS_LOCAL_STORAGE) {
localStorage.setItem(TR_DATA_CACHE_KEY, JSON.stringify(map))
}
})
return a.code
}
Expand Down
2 changes: 1 addition & 1 deletion dashboard/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ registerSW({
if (!registration) {
return
}
registration.sync.register('poll-state')
// registration.sync.register('poll-state')
},
})

Expand Down
34 changes: 14 additions & 20 deletions dashboard/src/sw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { clientsClaim } from 'workbox-core'
import { NavigationRoute, registerRoute } from 'workbox-routing'
import pako from 'pako'
import type { Stats } from '@/api/v0'
import { setLang } from '@/lang'
import { formatBytes, formatNumber } from '@/utils'

declare let self: ServiceWorkerGlobalScope

Expand All @@ -19,6 +21,8 @@ const ICON_URL = BASE_URL + '/favicon.ico'

console.log('PWA Service worker loading')

setLang('zh-CN') // TODO: do not hardcode translations

// self.__WB_MANIFEST is default injection point
precacheAndRoute(self.__WB_MANIFEST)

Expand Down Expand Up @@ -62,21 +66,6 @@ function decodeB64(b64: string): Uint8Array {

const bUnits = ['KB', 'MB', 'GB', 'TB']

function formatBytes(bytes: number): string {
if (bytes < 1000) {
return bytes.toString()
}
var unit
for (const u of bUnits) {
unit = u
bytes /= 1024
if (bytes < 1000) {
break
}
}
return `${bytes.toFixed(2)} ${unit}`
}

async function onRecvPush(data: PushData): Promise<void> {
switch (data.typ) {
case 'enabled':
Expand Down Expand Up @@ -108,16 +97,21 @@ async function onRecvPush(data: PushData): Promise<void> {
const lastTwoDay = new Date(
Date.UTC(stats.date.year, stats.date.month + 1, stats.date.day - 1, stats.date.hour),
)
const lastStat = stats.days[lastDay.getDate()]
const lastStat =
lastDay.getUTCMonth() === stats.date.month + 1
? stats.days[lastDay.getUTCDate()]
: stats.prev.days[lastDay.getUTCDate()]
const lastTwoStat =
lastDay.getMonth() === lastDay.getMonth()
? stats.days[lastTwoDay.getDate()]
: stats.prev.days[lastTwoDay.getDate()]
lastTwoDay.getUTCMonth() === stats.date.month + 1
? stats.days[lastTwoDay.getUTCDate()]
: stats.prev.days[lastTwoDay.getUTCDate()]
await self.registration
.showNotification('OpenBmclApi', {
icon: ICON_URL,
tag: `daily-report`,
body: `昨日数据: 流量 ${formatBytes(lastStat.bytes)}, 请求 ${lastStat.hits}`,
body: `昨日数据: 流量 ${formatBytes(lastStat.bytes)}, 请求 ${formatNumber(
lastStat.hits,
)}\n增长 ${formatBytes(lastStat.bytes - lastTwoStat.bytes)}`,
})
.catch((err) => console.error('notify error:', err))
break
Expand Down
32 changes: 25 additions & 7 deletions dashboard/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,18 @@ const _ZH = new Lang('zh')

export function formatNumber(num: number): string {
const lang = getLang()
var neg = ''
if (num < 0) {
neg = '-'
num = -num
}
var res: string
if (_ZH.match(lang)) {
return formatNumberZH(num)
res = formatNumberZH(num)
} else {
res = formatNumberEN(num)
}
return formatNumberEN(num)
return neg + res
}

const nUnitsUS = ['k', 'm', 'B', 'T', 'Q']
Expand All @@ -34,7 +42,7 @@ function formatNumberZH(num: number): string {
if (num < 9000) {
return num.toString()
}
var unit
var unit = ''
for (const u of nUnitsZH) {
unit = u
num /= 10000
Expand All @@ -48,21 +56,31 @@ function formatNumberZH(num: number): string {
const bUnits = ['KB', 'MB', 'GB', 'TB']

export function formatBytes(bytes: number): string {
var neg = ''
if (bytes < 0) {
neg = '-'
bytes = -bytes
}
if (bytes < 1000) {
return bytes.toString()
return `${neg}${bytes} B`
}
var unit
var unit = ''
for (const u of bUnits) {
unit = u
bytes /= 1024
if (bytes < 1000) {
break
}
}
return `${bytes.toFixed(2)} ${unit}`
return `${neg}${bytes.toFixed(2)} ${unit}`
}

export function formatTime(ms: number): string {
var neg = ''
if (ms < 0) {
neg = '-'
ms = -ms
}
var unit = tr('unit.time.ms')
if (ms > 800) {
ms /= 1000
Expand All @@ -84,5 +102,5 @@ export function formatTime(ms: number): string {
}
}
}
return `${ms.toFixed(2)} ${unit}`
return `${neg}${ms.toFixed(2)} ${unit}`
}
66 changes: 53 additions & 13 deletions dashboard/src/views/SettingsView.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<script setup lang="ts">
import { ref, reactive, computed, watch, inject, onMounted, type Ref } from 'vue'
import Card from 'primevue/card'
import Calendar from 'primevue/calendar'
import Dropdown from 'primevue/dropdown'
import InputIcon from 'primevue/inputicon'
import InputSwitch from 'primevue/inputswitch'
import { useToast } from 'primevue/usetoast'
import {
Expand Down Expand Up @@ -37,9 +39,25 @@ const settings = bindObjectToLocalStorage(
notifyWhenSyncFinished: false,
notifyUpdates: false,
dailyReport: false,
dailyReportAt: '00:00',
},
'go-openbmclapi.settings.notify',
)
const dailyReportAt = ref(
new Date(
0,
0,
0,
parseInt(settings.dailyReportAt.substr(0, 2)),
parseInt(settings.dailyReportAt.substr(3, 2)),
),
)
watch(dailyReportAt, (v: Date) => {
settings.dailyReportAt = `${v.getHours().toString().padStart(2, '0')}:${v
.getMinutes()
.toString()
.padStart(2, '0')}`
})
function getSubscribeScopes(): SubscribeScope[] {
const res: SubscribeScope[] = []
Expand Down Expand Up @@ -93,13 +111,6 @@ async function subscribe(): Promise<void> {
}
async function onEnableNotify(): Promise<void> {
if (enableNotify.value) {
if (token.value) {
removeSubscription(token.value).catch(console.error)
}
enableNotify.value = false
return
}
if (!token.value) {
toast.add({
severity: 'error',
Expand All @@ -108,6 +119,11 @@ async function onEnableNotify(): Promise<void> {
})
return
}
if (enableNotify.value) {
removeSubscription(token.value).catch(console.error)
enableNotify.value = false
return
}
requestingPermission.value = true
try {
if ((await Notification.requestPermission()) !== 'granted') {
Expand Down Expand Up @@ -221,41 +237,58 @@ onMounted(() => {
</div>
</template>
<template #content>
<div class="flex-row-center settings-elem">
<div class="settings-elem">
<lable class="settings-label">{{ tr('title.notify.when.disabled') }}</lable>
<InputSwitch
v-model="settings.notifyWhenDisabled"
:disabled="requestingPermission || !enableNotify"
/>
</div>
<div class="flex-row-center settings-elem">
<div class="settings-elem">
<lable class="settings-label">{{ tr('title.notify.when.enabled') }}</lable>
<InputSwitch
v-model="settings.notifyWhenEnabled"
:disabled="requestingPermission || !enableNotify"
/>
</div>
<div class="flex-row-center settings-elem">
<div class="settings-elem">
<lable class="settings-label">{{ tr('title.notify.when.sync.done') }}</lable>
<InputSwitch
v-model="settings.notifyWhenSyncFinished"
:disabled="requestingPermission || !enableNotify"
/>
</div>
<div class="flex-row-center settings-elem">
<div class="settings-elem">
<lable class="settings-label">{{ tr('title.notify.when.update.available') }}</lable>
<InputSwitch
v-model="settings.notifyUpdates"
:disabled="requestingPermission || !enableNotify"
/>
</div>
<div class="flex-row-center settings-elem">
<div class="settings-elem">
<lable class="settings-label">{{ tr('title.notify.report.daily') }}</lable>
<InputSwitch
v-model="settings.dailyReport"
:disabled="requestingPermission || !enableNotify"
/>
</div>
<div class="settings-elem">
<lable class="settings-label" style="margin-left: 1.5rem"
>{{ tr('title.notify.report.at') }}(TODO)</lable
>
<Calendar
class="time-input"
v-model="dailyReportAt"
showIcon
iconDisplay="input"
timeOnly
:stepMinute="15"
>
<template #inputicon="{ clickCallback }">
<InputIcon class="pi pi-clock pointer" @click="clickCallback" />
</template>
</Calendar>
</div>
</template>
</Card>
</div>
Expand All @@ -274,6 +307,9 @@ onMounted(() => {
}
.settings-elem {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 0.4rem 1rem;
Expand All @@ -285,7 +321,7 @@ onMounted(() => {
}
.settings-label {
width: calc(100% - 3rem);
max-width: calc(100% - 3rem);
}
.lang-selector .pi-globe {
Expand All @@ -296,6 +332,10 @@ onMounted(() => {
font-size: 0.9rem;
}
.time-input {
width: 7.5rem;
}
@media (max-width: 60rem) {
.settings-group {
width: 100%;
Expand Down

0 comments on commit fae98aa

Please sign in to comment.