add dashboard

This commit is contained in:
Litlyx
2024-06-01 15:27:40 +02:00
parent 75f0787c3b
commit df4faf366f
201 changed files with 91267 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
import type { MetricsTimeline } from "~/server/api/metrics/[project_id]/timeline/generic";
export const slicesData = {
hour: {
fromOffset: 1000 * 60 * 60 * 24
},
day: {
fromOffset: 1000 * 60 * 60 * 24 * 7
},
month: {
fromOffset: 1000 * 60 * 60 * 24 * 30 * 12
},
year: {
fromOffset: 1000 * 60 * 60 * 24 * 30 * 12 * 10
}
}
export type SliceName = keyof typeof slicesData;
export const hoursOffset = -(new Date().getTimezoneOffset() / 60);
function matchDateWithSlice(a: Date, b: Date, slice: SliceName): boolean {
if (a.getFullYear() != b.getFullYear()) return false;
if (a.getMonth() != b.getMonth()) return false;
if (slice === 'month') return true;
if (a.getDate() != b.getDate()) return false;
if (slice === 'day') return true;
if (a.getHours() != b.getHours()) return false;
if (slice === 'hour') return true;
return true;
}
type FixMetricsOptions = {
advanced?: boolean,
advancedGroupKey?: string,
timeLabels?: boolean
}
export function fixMetrics(result: { data: MetricsTimeline[], from: string, to: string }, slice: SliceName, _options?: FixMetricsOptions) {
const options = {
advanced: false,
advancedGroupKey: 'default',
timeLabels: false,
..._options
}
const allDates: Date[] = [];
let currentDate = new Date(result.from);
while (currentDate <= new Date(result.to)) {
allDates.push(new Date(currentDate));
if (slice == 'hour') {
currentDate.setHours(currentDate.getHours() + 1);
} else if (slice == 'day') {
currentDate.setDate(currentDate.getDate() + 1);
} else if (slice == 'month') {
currentDate.setMonth(currentDate.getMonth() + 1);
} else if (slice == 'year') {
currentDate.setFullYear(currentDate.getFullYear() + 1);
}
}
const allKeys = !options.advanced ? [] : Array.from(new Set(result.data.map((e: any) => e[options.advancedGroupKey])).values());
const fixed: any[] = allDates.map(matchDate => {
if (!options.advanced) {
const target = result.data.find(e => matchDateWithSlice(new Date(e._id), matchDate, slice));
return { _id: target ? new Date(target._id) : matchDate, count: target?.count || 0 }
}
const targets = result.data.filter(e => matchDateWithSlice(new Date(e._id), matchDate, slice));
const returnObject: any = {
_id: targets.length == 0 ? matchDate : new Date(targets[0]._id),
count: allKeys.map(e => {
return {
key: e,
value: targets.find((k: any) => k[options.advancedGroupKey] == e)?.count || 0
}
})
}
return returnObject;
});
if (slice === 'day' || slice == 'hour') fixed.pop();
const data = fixed.map(e => e.count);
const avgTrend = data.slice(0, -1).reduce((a, e) => a + e, 0) / (data.length - 1);
const t = data.at(-1) || 0;
const trend = (100 / avgTrend * t) - 100;
return {
labels: options.timeLabels ?
fixed.map(e => {
return e._id;
}) : fixed.map(e => {
if (slice == 'hour') {
return `${e._id.getHours().toString().padStart(2, '0')}:00`
} else if (slice == 'day') {
return `${e._id.getDate().toString().padStart(2, '0')}/${e._id.getMonth().toString().padStart(2, '0')}`
} else if (slice == 'month') {
return `${e._id.getMonth().toString().padStart(2, '0')}/${e._id.getFullYear().toString()}`
} else if (slice == 'year') {
return `${e._id.getFullYear().toString()}`
} else {
return '???'
}
}),
data,
trend,
allKeys
}
}

View File

@@ -0,0 +1,10 @@
export const debounce = <F extends (...args: any) => any>(func: F, waitFor: number,) => {
let timeout: any;
const debounced = (...args: any) => {
clearTimeout(timeout)
timeout = setTimeout(() => func(...args), waitFor)
}
return debounced as (...args: Parameters<F>) => ReturnType<F>
}

View File

@@ -0,0 +1,6 @@
export function parseText(text: string) {
const entityRegex = /&#(\d+);/g;
return text.replace(entityRegex, (match, dec) => {
return String.fromCharCode(dec);
}).replace(/&amp;/g, '&');
}

View File

@@ -0,0 +1,14 @@
export function prettyNumber000(value: number | string) {
return Math.floor(parseInt(value.toString())).toLocaleString('en-EN').replace(/,/g, '.');
}
export function formatNumberK(value: string | number, decimals: number = 1) {
const num = parseInt(value.toString());
if (num > 1_000_000) return (num / 1_000_000).toFixed(decimals) + ' M';
if (num > 1_000) return (num / 1_000).toFixed(decimals) + ' K';
return num.toFixed();
}