diff --git a/assets/auto-imports.d.ts b/assets/auto-imports.d.ts index 2b3a3f4c..2a23a99c 100644 --- a/assets/auto-imports.d.ts +++ b/assets/auto-imports.d.ts @@ -151,6 +151,7 @@ declare global { const toReactive: typeof import('@vueuse/core')['toReactive'] const toRef: typeof import('vue')['toRef'] const toRefs: typeof import('vue')['toRefs'] + const toRelativeTime: typeof import('./utils/index')['toRelativeTime'] const toValue: typeof import('vue')['toValue'] const triggerRef: typeof import('vue')['triggerRef'] const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount'] @@ -542,6 +543,7 @@ declare module 'vue' { readonly toReactive: UnwrapRef readonly toRef: UnwrapRef readonly toRefs: UnwrapRef + readonly toRelativeTime: UnwrapRef readonly toValue: UnwrapRef readonly triggerRef: UnwrapRef readonly tryOnBeforeMount: UnwrapRef diff --git a/assets/components.d.ts b/assets/components.d.ts index 31ab73a3..760af9b5 100644 --- a/assets/components.d.ts +++ b/assets/components.d.ts @@ -105,6 +105,7 @@ declare module 'vue' { 'Ph:stackSimple': typeof import('~icons/ph/stack-simple')['default'] Popup: typeof import('./components/Popup.vue')['default'] RandomColorTag: typeof import('./components/LogViewer/RandomColorTag.vue')['default'] + RelativeTime: typeof import('./components/common/RelativeTime.vue')['default'] 'Ri:terminalWindowFill': typeof import('~icons/ri/terminal-window-fill')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] diff --git a/assets/components/Announcements.vue b/assets/components/Announcements.vue index 70cee2dc..c229dfb3 100644 --- a/assets/components/Announcements.vue +++ b/assets/components/Announcements.vue @@ -22,7 +22,7 @@ > {{ release.name }} - +
{{ release.body }} @@ -39,7 +39,7 @@ > {{ release.name }} - + {{ $t("releases.latest") }} diff --git a/assets/components/ContainerDropdown.vue b/assets/components/ContainerDropdown.vue index 6992e960..dd8169f7 100644 --- a/assets/components/ContainerDropdown.vue +++ b/assets/components/ContainerDropdown.vue @@ -10,7 +10,7 @@ >
{{ other.name }}
running
- + diff --git a/assets/components/ContainerPopup.vue b/assets/components/ContainerPopup.vue index afd69baf..0753174b 100644 --- a/assets/components/ContainerPopup.vue +++ b/assets/components/ContainerPopup.vue @@ -1,28 +1,32 @@ diff --git a/assets/components/common/RelativeTime.vue b/assets/components/common/RelativeTime.vue new file mode 100644 index 00000000..8273b1e7 --- /dev/null +++ b/assets/components/common/RelativeTime.vue @@ -0,0 +1,17 @@ + + + diff --git a/assets/utils/index.ts b/assets/utils/index.ts index 70e1753b..6e60e7eb 100644 --- a/assets/utils/index.ts +++ b/assets/utils/index.ts @@ -109,3 +109,27 @@ export function hashCode(str: string) { } return hash; } + +const units: [Intl.RelativeTimeFormatUnit, number][] = [ + ["year", 31536000], + ["month", 2592000], + ["week", 604800], + ["day", 86400], + ["hour", 3600], + ["minute", 60], + ["second", 1], +]; + +export function toRelativeTime(date: Date, locale: string | undefined): string { + const diffInSeconds = (date.getTime() - new Date().getTime()) / 1000; + const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" }); + + for (const [unit, seconds] of units) { + const value = Math.round(diffInSeconds / seconds); + if (Math.abs(value) >= 1) { + return rtf.format(value, unit); + } + } + + return rtf.format(0, "second"); +} diff --git a/package.json b/package.json index 997f179b..baf854fa 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,6 @@ "d3-shape": "^3.2.0", "d3-transition": "^3.0.1", "daisyui": "5.0.35", - "date-fns": "^4.1.0", "entities": "^6.0.0", "fuse.js": "^7.1.0", "lodash.debounce": "^4.0.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ecba398e..2229bec8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -86,9 +86,6 @@ importers: daisyui: specifier: 5.0.35 version: 5.0.35 - date-fns: - specifier: ^4.1.0 - version: 4.1.0 entities: specifier: ^6.0.0 version: 6.0.0 @@ -2364,9 +2361,6 @@ packages: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} - date-fns@4.1.0: - resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} - de-indent@1.0.2: resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} @@ -6075,8 +6069,6 @@ snapshots: whatwg-mimetype: 4.0.0 whatwg-url: 14.2.0 - date-fns@4.1.0: {} - de-indent@1.0.2: {} debug@4.4.0: