From e03026e1d292630ac0539d6b1e8352e35b6e1bb2 Mon Sep 17 00:00:00 2001 From: Sergei Birukov Date: Sun, 24 Mar 2024 17:00:46 +0300 Subject: [PATCH] Add timeago. Fix locales --- webui/package-lock.json | 53 ++++++++++++++++++++++ webui/package.json | 4 +- webui/src/App.vue | 36 +++++++++++---- webui/src/components/ClientAddress.vue | 20 ++++++-- webui/src/components/ClientInfo.vue | 13 ++---- webui/src/components/ClientTrafficStat.vue | 4 +- webui/src/composables/useTimeAgo.js | 29 ------------ webui/src/main.js | 17 ++++++- webui/src/store/store.js | 5 +- 9 files changed, 125 insertions(+), 56 deletions(-) delete mode 100644 webui/src/composables/useTimeAgo.js diff --git a/webui/package-lock.json b/webui/package-lock.json index c6175953..2947485f 100644 --- a/webui/package-lock.json +++ b/webui/package-lock.json @@ -10,9 +10,11 @@ "dependencies": { "apexcharts": "^3.48.0", "crypto-js": "^4.2.0", + "date-fns": "^3.6.0", "pinia": "^2.1.7", "vue": "^3.3.11", "vue-i18n": "^9.10.2", + "vue-timeago3": "^2.3.2", "vue3-apexcharts": "^1.5.2" }, "devDependencies": { @@ -60,6 +62,17 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/runtime": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", + "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.19.11", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz", @@ -1523,6 +1536,15 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -3050,6 +3072,11 @@ "node": ">=8.10.0" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -3829,6 +3856,32 @@ "vue": "^3.0.0" } }, + "node_modules/vue-timeago3": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/vue-timeago3/-/vue-timeago3-2.3.2.tgz", + "integrity": "sha512-yxb++H9ekLS8bSt3in7fMwIfW1ex9ceMYVCcfLiOppBYpp8hatlOTLqQyCmLXeDYB098uwgfnCewEPKVh/gi6A==", + "dependencies": { + "date-fns": "^2.28.0" + }, + "peerDependencies": { + "vue": "^3.3.6" + } + }, + "node_modules/vue-timeago3/node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/vue3-apexcharts": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/vue3-apexcharts/-/vue3-apexcharts-1.5.2.tgz", diff --git a/webui/package.json b/webui/package.json index ebf6ae5c..9edf5518 100644 --- a/webui/package.json +++ b/webui/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "dev": "vite", + "dev": "vite --host", "build": "vite build", "build:watch": "vite build --watch", "preview": "vite preview" @@ -12,9 +12,11 @@ "dependencies": { "apexcharts": "^3.48.0", "crypto-js": "^4.2.0", + "date-fns": "^3.6.0", "pinia": "^2.1.7", "vue": "^3.3.11", "vue-i18n": "^9.10.2", + "vue-timeago3": "^2.3.2", "vue3-apexcharts": "^1.5.2" }, "devDependencies": { diff --git a/webui/src/App.vue b/webui/src/App.vue index 3c0f047b..5de9147b 100644 --- a/webui/src/App.vue +++ b/webui/src/App.vue @@ -64,6 +64,7 @@ diff --git a/webui/src/components/ClientTrafficStat.vue b/webui/src/components/ClientTrafficStat.vue index 315ce38e..01f7467a 100644 --- a/webui/src/components/ClientTrafficStat.vue +++ b/webui/src/components/ClientTrafficStat.vue @@ -24,11 +24,11 @@ const { bytes } = useBytes(); defineProps({ transferData: { - type: Object, + type: Number, default: null, }, transferDataCurrent: { - type: Object, + type: Number, default: null, }, type: { diff --git a/webui/src/composables/useTimeAgo.js b/webui/src/composables/useTimeAgo.js deleted file mode 100644 index 31f25c77..00000000 --- a/webui/src/composables/useTimeAgo.js +++ /dev/null @@ -1,29 +0,0 @@ -export function useTimeAgo() { - const timeago = (date) => { - const now = new Date(); - const diff = now - date; - - if (diff < 1000) { - return 'just now'; - } else if (diff < 60000) { - const seconds = Math.floor(diff / 1000); - return `${seconds} ${plural('second', seconds)} ago`; - } else if (diff < 3600000) { - const minutes = Math.floor(diff / 60000); - return `${minutes} ${plural('minute', minutes)} ago`; - } else if (diff < 86400000) { - const hours = Math.floor(diff / 3600000); - return `${hours} ${plural('hour', hours)} ago`; - } else { - const days = Math.floor(diff / 86400000); - return `${days} ${plural('day', days)} ago`; - } - }; - - // #278 -- this function might need to be rewritten to support l18n - const plural = (word, count) => { - return count !== 1 ? `${word}s` : word; - }; - - return { timeago }; -} diff --git a/webui/src/main.js b/webui/src/main.js index 65fb0298..097cf1ca 100644 --- a/webui/src/main.js +++ b/webui/src/main.js @@ -5,12 +5,27 @@ import { createApp } from 'vue'; import { createI18n } from 'vue-i18n'; import { createPinia } from 'pinia'; import { messages } from '@/utils/i18n'; +import timeago from 'vue-timeago3'; const i18n = createI18n({ + legacy: false, locale: localStorage.getItem('lang') || 'en', allowComposition: true, fallbackLocale: 'en', messages, }); + const pinia = createPinia(); -createApp(App).use(i18n).use(pinia).mount('#app'); + +const timeagoOptions = { + converterOptions: { + includeSeconds: false, + addSuffix: true, + }, +}; + +const app = createApp(App); +app.use(i18n); +app.use(pinia); +app.use(timeago, timeagoOptions); +app.mount('#app'); diff --git a/webui/src/store/store.js b/webui/src/store/store.js index 2e69f2f6..c6bfead5 100644 --- a/webui/src/store/store.js +++ b/webui/src/store/store.js @@ -18,6 +18,8 @@ export const useStore = defineStore('store', () => { const clientCreateShowModal = ref(null); const clientCreateName = ref(''); const qrcode = ref(null); + const lang = ref('en'); + const dateFnsLocale = ref(); const uiTheme = ref(localStorage.theme || 'auto'); const prefersDarkScheme = ref(window.matchMedia('(prefers-color-scheme: dark)')); @@ -107,7 +109,6 @@ export const useStore = defineStore('store', () => { // Debug client.transferRx = clientsPersist[client.id].transferRxPrevious + Math.random() * 1000; client.transferTx = clientsPersist[client.id].transferTxPrevious + Math.random() * 1000; - client.latestHandshakeAt = new Date('2024-03-20'); updateCharts = true; // DEV TODO: Update. Get from settings if (updateCharts) { @@ -179,6 +180,8 @@ export const useStore = defineStore('store', () => { qrcode, uiTheme, prefersDarkScheme, + lang, + dateFnsLocale, uiChartType, uiShowCharts, uiTrafficStats,