mirror of
https://github.com/unraid/api.git
synced 2026-01-04 23:50:37 -06:00
feat: uptime and expire time component
This commit is contained in:
56
components/UptimeExpire.vue
Normal file
56
components/UptimeExpire.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<script setup lang="ts">
|
||||
import dateDiff from '~/helpers/time/dateDiff';
|
||||
import dateFormat from '~/helpers/time/dateFormat';
|
||||
import buildStringFromValues from '~/helpers/time/buildTimeString';
|
||||
|
||||
export interface Props {
|
||||
time: string;
|
||||
state: string;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const parsedTime = ref<string>('');
|
||||
const formattedTime = computed<string>(() => {
|
||||
return dateFormat(props.time);
|
||||
});
|
||||
|
||||
const countUp = computed<boolean>(() => {
|
||||
return props.state !== 'TRIAL' && props.state === 'EEXPIRED';
|
||||
})
|
||||
|
||||
const output = computed(() => {
|
||||
if (!countUp.value) {
|
||||
return {
|
||||
title: props.state === 'EEXPIRED'
|
||||
? `Trial Key Expired at ${formattedTime.value}`
|
||||
: `Trial Key Expires at ${formattedTime.value}`,
|
||||
text: props.state === 'EEXPIRED'
|
||||
? `Trial Key Expired ${parsedTime.value}`
|
||||
: `Trial Key Expires in ${parsedTime.value}`,
|
||||
};
|
||||
}
|
||||
return {
|
||||
title: `Server Up Since ${formattedTime.value}`,
|
||||
text: `Uptime ${parsedTime.value}`,
|
||||
};
|
||||
});
|
||||
|
||||
const runDiff = () => parsedTime.value = buildStringFromValues(dateDiff(props.time, countUp.value));
|
||||
|
||||
let interval: string | number | NodeJS.Timeout | undefined = undefined;
|
||||
onBeforeMount(() => {
|
||||
runDiff();
|
||||
interval = setInterval(() => {
|
||||
runDiff();
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
clearInterval(interval);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p :title="output.title">{{ output.text }}</p>
|
||||
</template>
|
||||
42
helpers/time/buildTimeString.ts
Normal file
42
helpers/time/buildTimeString.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { TimeStringsObject } from '~/types/time';
|
||||
|
||||
const buildStringFromValues = ({
|
||||
years, months, days, hours, minutes, seconds, firstDateWasLater, displaySeconds,
|
||||
}: TimeStringsObject) => {
|
||||
const result = [];
|
||||
|
||||
type DateStrings = {
|
||||
[key: string]: string;
|
||||
};
|
||||
const dateStrings: DateStrings = {
|
||||
year: 'year',
|
||||
years: 'years',
|
||||
month: 'month',
|
||||
months: 'months',
|
||||
day: 'day',
|
||||
days: 'days',
|
||||
hour: 'hour',
|
||||
hours: 'hours',
|
||||
minute: 'minute',
|
||||
minutes: 'minutes',
|
||||
second: 'second',
|
||||
seconds: 'seconds',
|
||||
firstDateWasLater: 'ago',
|
||||
delimiter: ' ',
|
||||
};
|
||||
const pluralize = (num: number, word: string) => {
|
||||
const index = word + (num === 1 ? '' : 's');
|
||||
return `${num} ${dateStrings[index]}`;
|
||||
};
|
||||
|
||||
if (years) result.push(pluralize(years, 'year'));
|
||||
if (months) result.push(pluralize(months, 'month'));
|
||||
if (days) result.push(pluralize(days, 'day'));
|
||||
if (hours) result.push(pluralize(hours, 'hour'));
|
||||
if (minutes) result.push(pluralize(minutes, 'minute'));
|
||||
if (seconds && ((!years && !months && !days && !hours && !minutes) || displaySeconds)) result.push(pluralize(seconds, 'second'));
|
||||
if (firstDateWasLater) result.push(dateStrings.firstDateWasLater);
|
||||
return result.join(dateStrings.delimiter);
|
||||
}
|
||||
|
||||
export default buildStringFromValues;
|
||||
11
helpers/time/dateDiff.ts
Normal file
11
helpers/time/dateDiff.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import dayjs from 'dayjs';
|
||||
import preciseDateDiff from './preciseDateDiff';
|
||||
|
||||
const readbleDifference = (a = '', b = '') => {
|
||||
const x = a ? dayjs(parseInt(a, 10)) : dayjs();
|
||||
const y = b ? dayjs(parseInt(b, 10)) : dayjs();
|
||||
return preciseDateDiff(x, y);
|
||||
};
|
||||
const dateDiff = (time: string, countUp: boolean) => countUp ? readbleDifference(time, '') : readbleDifference('', time);
|
||||
|
||||
export default dateDiff;
|
||||
5
helpers/time/dateFormat.ts
Normal file
5
helpers/time/dateFormat.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const formatDate = (date: string): string => dayjs(parseInt(date, 10)).format('llll');
|
||||
|
||||
export default formatDate;
|
||||
72
helpers/time/preciseDateDiff.ts
Normal file
72
helpers/time/preciseDateDiff.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import dayjs from 'dayjs';
|
||||
import { TimeStringsObject } from '~/types/time';
|
||||
|
||||
/**
|
||||
* Original meat and potatos from:
|
||||
* @version: 1.0.1
|
||||
* @author: huangjinlin
|
||||
* @repo: https://github.com/huangjinlin/dayjs-precise-range
|
||||
*/
|
||||
const buildValueObject = (yDiff: number, mDiff: number, dDiff: number, hourDiff: number, minDiff: number, secDiff: number, firstDateWasLater: boolean): TimeStringsObject => ({
|
||||
years: yDiff,
|
||||
months: mDiff,
|
||||
days: dDiff,
|
||||
hours: hourDiff,
|
||||
minutes: minDiff,
|
||||
seconds: secDiff,
|
||||
firstDateWasLater,
|
||||
});
|
||||
const preciseDateDiff = (d1: dayjs.Dayjs, d2: dayjs.Dayjs): TimeStringsObject => {
|
||||
let m1 = dayjs(d1);
|
||||
let m2 = dayjs(d2);
|
||||
let firstDateWasLater;
|
||||
|
||||
if (m1.isSame(m2)) {
|
||||
return buildValueObject(0, 0, 0, 0, 0, 0, false);
|
||||
}
|
||||
if (m1.isAfter(m2)) {
|
||||
const tmp = m1;
|
||||
m1 = m2;
|
||||
m2 = tmp;
|
||||
firstDateWasLater = true;
|
||||
} else {
|
||||
firstDateWasLater = false;
|
||||
}
|
||||
|
||||
let yDiff = m2.year() - m1.year();
|
||||
let mDiff = m2.month() - m1.month();
|
||||
let dDiff = m2.date() - m1.date();
|
||||
let hourDiff = m2.hour() - m1.hour();
|
||||
let minDiff = m2.minute() - m1.minute();
|
||||
let secDiff = m2.second() - m1.second();
|
||||
|
||||
if (secDiff < 0) {
|
||||
secDiff = 60 + secDiff;
|
||||
minDiff -= 1;
|
||||
}
|
||||
if (minDiff < 0) {
|
||||
minDiff = 60 + minDiff;
|
||||
hourDiff -= 1;
|
||||
}
|
||||
if (hourDiff < 0) {
|
||||
hourDiff = 24 + hourDiff;
|
||||
dDiff -= 1;
|
||||
}
|
||||
if (dDiff < 0) {
|
||||
const daysInLastFullMonth = dayjs(`${m2.year()}-${m2.month() + 1}`).subtract(1, 'M').daysInMonth();
|
||||
if (daysInLastFullMonth < m1.date()) { // 31/01 -> 2/03
|
||||
dDiff = daysInLastFullMonth + dDiff + (m1.date() - daysInLastFullMonth);
|
||||
} else {
|
||||
dDiff = daysInLastFullMonth + dDiff;
|
||||
}
|
||||
mDiff -= 1;
|
||||
}
|
||||
if (mDiff < 0) {
|
||||
mDiff = 12 + mDiff;
|
||||
yDiff -= 1;
|
||||
}
|
||||
|
||||
return buildValueObject(yDiff, mDiff, dDiff, hourDiff, minDiff, secDiff, firstDateWasLater);
|
||||
};
|
||||
|
||||
export default preciseDateDiff;
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -8,7 +8,8 @@
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@pinia/nuxt": "^0.4.11",
|
||||
"crypto-js": "^4.1.1"
|
||||
"crypto-js": "^4.1.1",
|
||||
"dayjs": "^1.11.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxtjs/tailwindcss": "^6.7.0",
|
||||
@@ -3703,6 +3704,11 @@
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.7",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz",
|
||||
"integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ=="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@pinia/nuxt": "^0.4.11",
|
||||
"crypto-js": "^4.1.1"
|
||||
"crypto-js": "^4.1.1",
|
||||
"dayjs": "^1.11.7"
|
||||
},
|
||||
"overrides": {
|
||||
"vue": "latest"
|
||||
|
||||
10
types/time.ts
Normal file
10
types/time.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export interface TimeStringsObject {
|
||||
years: number;
|
||||
months: number;
|
||||
days: number;
|
||||
hours: number;
|
||||
minutes: number;
|
||||
seconds: number;
|
||||
firstDateWasLater: boolean;
|
||||
displaySeconds?: boolean;
|
||||
};
|
||||
Reference in New Issue
Block a user