mirror of
https://github.com/rajnandan1/kener.git
synced 2026-06-23 04:10:22 +00:00
refactor: update tooltip styles and improve component structure across multiple files
This commit is contained in:
@@ -43,7 +43,11 @@
|
||||
style="border-radius: var(--radius-3xl)"
|
||||
>
|
||||
{#if item.iconURL}
|
||||
<img src={clientResolver(resolve, item.iconURL)} alt={item.name} class="mr-2 h-4 w-4" />
|
||||
<img
|
||||
src={clientResolver(resolve, item.iconURL)}
|
||||
alt={item.name}
|
||||
class="mr-2 h-4 w-4 object-cover"
|
||||
/>
|
||||
{/if}
|
||||
{item.name}
|
||||
</a>
|
||||
|
||||
@@ -307,11 +307,12 @@
|
||||
{#if hoveredMinute}
|
||||
<div
|
||||
bind:this={tooltipEl}
|
||||
class="bg-foreground text-secondary pointer-events-none absolute z-20 w-max -translate-x-1/2 rounded-md px-2 py-1 text-xs font-medium whitespace-nowrap"
|
||||
class="bg-popover text-popover-foreground border-border pointer-events-none absolute z-20 w-max -translate-x-1/2 rounded-md border px-2 py-1 text-xs font-medium whitespace-nowrap"
|
||||
style={tooltipStyle}
|
||||
>
|
||||
{$formatDate(hoveredMinute.data.timestamp, "HH:mm")} -
|
||||
<span class="text-{hoveredMinute.data.status.toLowerCase()}">{$t(hoveredMinute.data.status)}</span>
|
||||
<span class="text-{hoveredMinute.data.status.toLowerCase()}">
|
||||
{$t(hoveredMinute.data.status)} @ {$formatDate(hoveredMinute.data.timestamp, "HH:mm")}
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
import { getEndOfDayAtTz } from "$lib/client/datetime";
|
||||
import { formatDate } from "$lib/stores/datetime";
|
||||
import clientResolver from "$lib/client/resolver.js";
|
||||
import { ArrowDown } from "@lucide/svelte";
|
||||
import MonitorBar from "./MonitorBar.svelte";
|
||||
interface Props {
|
||||
monitorTag: string;
|
||||
class?: string;
|
||||
|
||||
@@ -365,14 +365,14 @@
|
||||
{#if hoveredBar}
|
||||
<div
|
||||
bind:this={tooltipEl}
|
||||
class="bg-foreground text-secondary pointer-events-none absolute z-20 w-max -translate-x-1/2 rounded-md px-2 py-1 text-xs font-medium whitespace-nowrap"
|
||||
class="bg-popover text-popver-foreground pointer-events-none absolute z-20 w-max -translate-x-1/2 rounded-md border px-2 py-1 text-xs font-medium whitespace-nowrap"
|
||||
style={tooltipStyle}
|
||||
>
|
||||
<span class={getStatusColor(hoveredBar.data)}>{$t(GetStatusSummary(hoveredBar.data))}</span>
|
||||
<span class="text-muted">@</span>
|
||||
<span class="text-muted-foreground">@</span>
|
||||
{$formatDate(hoveredBar.data.ts, "d MMM yyyy")}
|
||||
{#if hoveredBar.data.avgLatency > 0}
|
||||
<span class="text-muted ml-1">|</span>
|
||||
<span class="text-muted-foreground ml-1">|</span>
|
||||
<span class="ml-1">{ParseLatency(hoveredBar.data.avgLatency)}</span>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -315,6 +315,13 @@ export const push = async (monitor_tag: string, ts: number, status: string, opti
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
options.removeOnComplete = {
|
||||
age: 300, // keep up to 5 minutes
|
||||
count: 100, // keep up to 100 jobs
|
||||
};
|
||||
options.removeOnFail = {
|
||||
age: 24 * 3600, // keep up to 24 hours
|
||||
};
|
||||
const queue = getQueue();
|
||||
addWorker();
|
||||
|
||||
|
||||
@@ -71,6 +71,13 @@ export const push = async (jobData: EmailJobData, options?: JobsOptions) => {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
options.removeOnComplete = {
|
||||
age: 300, // keep up to 5 minutes
|
||||
count: 100, // keep up to 100 jobs
|
||||
};
|
||||
options.removeOnFail = {
|
||||
age: 24 * 3600, // keep up to 24 hours
|
||||
};
|
||||
|
||||
const queue = getQueue();
|
||||
addWorker();
|
||||
|
||||
@@ -195,6 +195,13 @@ export const push = async (monitor: MonitorRecordTyped, ts: number, options?: Jo
|
||||
id: deDupId,
|
||||
};
|
||||
}
|
||||
options.removeOnComplete = {
|
||||
age: 3600, // keep up to 1 hour
|
||||
count: 1000, // keep up to 1000 jobs
|
||||
};
|
||||
options.removeOnFail = {
|
||||
age: 24 * 3600, // keep up to 24 hours
|
||||
};
|
||||
const queue = getQueue();
|
||||
addWorker();
|
||||
await queue.add(
|
||||
|
||||
@@ -76,6 +76,13 @@ export const push = async (monitorTag: string, ts: number, result: MonitoringRes
|
||||
id: deDupId,
|
||||
};
|
||||
}
|
||||
options.removeOnComplete = {
|
||||
age: 300, // keep up to 5 minutes
|
||||
count: 100, // keep up to 100 jobs
|
||||
};
|
||||
options.removeOnFail = {
|
||||
age: 24 * 3600, // keep up to 24 hours
|
||||
};
|
||||
const queue = getQueue();
|
||||
addWorker();
|
||||
await queue.add(
|
||||
|
||||
@@ -93,7 +93,16 @@ export const push = async (variables: SubscriptionVariableMap, options?: JobsOpt
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
options.removeOnComplete = {
|
||||
age: 300, // keep up to 5 minutes
|
||||
count: 100, // keep up to 100 jobs
|
||||
};
|
||||
options.removeOnFail = {
|
||||
age: 24 * 3600, // keep up to 24 hours
|
||||
};
|
||||
const queue = getQueue();
|
||||
addWorker();
|
||||
|
||||
|
||||
@@ -87,6 +87,13 @@ export const start = async (options?: JobSchedulerTemplateOptions) => {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
options.removeOnComplete = {
|
||||
age: 300, // keep up to 5 minutes
|
||||
count: 100, // keep up to 100 jobs
|
||||
};
|
||||
options.removeOnFail = {
|
||||
age: 24 * 3600, // keep up to 24 hours
|
||||
};
|
||||
|
||||
const queue = getQueue();
|
||||
addWorker();
|
||||
|
||||
@@ -137,7 +137,13 @@ export const start = async (options?: JobSchedulerTemplateOptions) => {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
options.removeOnComplete = {
|
||||
age: 300, // keep up to 5 minutes
|
||||
count: 100, // keep up to 100 jobs
|
||||
};
|
||||
options.removeOnFail = {
|
||||
age: 24 * 3600, // keep up to 24 hours
|
||||
};
|
||||
const queue = getQueue();
|
||||
addWorker();
|
||||
|
||||
|
||||
@@ -46,6 +46,16 @@ export const addJobToSchedulerQueue = async (
|
||||
if (!monitor.cron) {
|
||||
throw new Error("Monitor cron expression is undefined");
|
||||
}
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
options.removeOnComplete = {
|
||||
age: 300, // keep up to 5 minutes
|
||||
count: 100, // keep up to 100 jobs
|
||||
};
|
||||
options.removeOnFail = {
|
||||
age: 24 * 3600, // keep up to 24 hours
|
||||
};
|
||||
const queue = getQueue(minNumOfWorkers);
|
||||
await queue.upsertJobScheduler(
|
||||
id,
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
let expandedGroups = $state<string[]>([]);
|
||||
let expandedPages = $state<string[]>([]);
|
||||
let prevSlug = $state(currentSlug);
|
||||
let prevSlug = $state("");
|
||||
|
||||
// Auto-expand when navigating to a different page (not when manually toggling)
|
||||
$effect(() => {
|
||||
@@ -102,7 +102,7 @@
|
||||
</script>
|
||||
|
||||
<nav class="p-6 pr-4 pl-10">
|
||||
<div class="flex flex-col gap-6">
|
||||
<div class="scrollbar-hidden flex flex-col gap-6">
|
||||
{#each config.sidebar as group (group.group)}
|
||||
<div class="mb-2">
|
||||
{#if group.collapsible}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
{/if}
|
||||
{@html `
|
||||
<style id="dynamic-styles">
|
||||
.kener-public {
|
||||
body {
|
||||
--up: ${data.siteStatusColors.UP};
|
||||
--degraded: ${data.siteStatusColors.DEGRADED};
|
||||
--down: ${data.siteStatusColors.DOWN};
|
||||
@@ -31,7 +31,7 @@
|
||||
--accent-foreground: ${data.siteStatusColors.ACCENT_FOREGROUND || data.siteStatusColors.ACCENT || "#e96e2d"};
|
||||
${data.font?.family ? `--font-family:'${data.font.family}', sans-serif;` : ""}
|
||||
}
|
||||
:is(.dark) .kener-public {
|
||||
:is(.dark) body {
|
||||
--up: ${data.siteStatusColorsDark.UP};
|
||||
--degraded: ${data.siteStatusColorsDark.DEGRADED};
|
||||
--down: ${data.siteStatusColorsDark.DOWN};
|
||||
@@ -58,6 +58,7 @@
|
||||
* {
|
||||
font-family: var(--font-family);
|
||||
}
|
||||
|
||||
/*
|
||||
:global(.text-3xl) {
|
||||
font-family: var(--font-family);
|
||||
|
||||
@@ -12,12 +12,18 @@ import type { TimestampStatusCount } from "$lib/server/types/db";
|
||||
import { GetNowTimestampUTC, UptimeCalculator } from "$lib/server/tool";
|
||||
import GC from "$lib/global-constants.js";
|
||||
import { GetStatusColor, GetStatusSummary, ParseLatency } from "$lib/clientTools";
|
||||
import { GetMonitorsParsed } from "$lib/server/controllers/monitorsController";
|
||||
import type { GroupMonitorTypeData } from "$lib/server/types/monitor";
|
||||
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
const { monitor_tag } = params;
|
||||
|
||||
// Validate monitor exists
|
||||
const monitor = await db.getMonitorByTag(monitor_tag);
|
||||
const monitors = await GetMonitorsParsed({ tag: monitor_tag });
|
||||
if (!monitors || monitors.length === 0) {
|
||||
throw error(404, { message: "Monitor not found" });
|
||||
}
|
||||
const monitor = monitors[0];
|
||||
if (!monitor) {
|
||||
throw error(404, { message: "Monitor not found" });
|
||||
}
|
||||
@@ -51,6 +57,12 @@ export const load: PageServerLoad = async ({ params }) => {
|
||||
};
|
||||
|
||||
//get status summary
|
||||
let extendedTags: string[] = [];
|
||||
if (monitor.monitor_type === "GROUP") {
|
||||
const groupData = monitor.type_data as GroupMonitorTypeData;
|
||||
const memberTags = groupData.monitors.map((m) => m.tag);
|
||||
extendedTags = extendedTags.concat(memberTags);
|
||||
}
|
||||
|
||||
return {
|
||||
monitorTag: monitor_tag,
|
||||
@@ -68,5 +80,6 @@ export const load: PageServerLoad = async ({ params }) => {
|
||||
pastMaintenances,
|
||||
upcomingMaintenances,
|
||||
externalUrl: monitor.external_url,
|
||||
extendedTags,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
import ArrowUpRight from "@lucide/svelte/icons/arrow-up-right";
|
||||
import clientResolver from "$lib/client/resolver.js";
|
||||
import { resolve } from "$app/paths";
|
||||
import { ArrowDown } from "@lucide/svelte";
|
||||
import MonitorBar from "$lib/components/MonitorBar.svelte";
|
||||
let { data } = $props();
|
||||
|
||||
// State
|
||||
@@ -117,6 +119,22 @@
|
||||
<!-- Calendar View (self-contained component with its own API call) -->
|
||||
<MonitorOverview monitorTag={data.monitorTag} class="mb-4" />
|
||||
|
||||
{#if data.extendedTags.length > 0}
|
||||
<!-- Included monitors -->
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col rounded-3xl border">
|
||||
<div class="flex items-center justify-between px-4 pt-4 pb-0">
|
||||
<Badge variant="secondary" class="gap-1">{$t("Available Components")}</Badge>
|
||||
</div>
|
||||
{#each data.extendedTags as tag, i}
|
||||
<div class="{i < data.extendedTags.length - 1 ? 'border-b' : ''} py-2 pb-4">
|
||||
<MonitorBar {tag} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- recent incidents -->
|
||||
<IncidentMonitorList incidents={data.resolvedIncidents} title="Recent Incidents" class="mt-4 mb-4" />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user