mirror of
https://github.com/rajnandan1/kener.git
synced 2026-08-07 15:27:13 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f33c02064 | |||
| 46c1a392b8 | |||
| c6880c5df6 | |||
| 646da94ef9 | |||
| 36ede93dce | |||
| 9ed35589f7 | |||
| e946dd18e0 | |||
| 51cad598c1 | |||
| 0595f23c18 | |||
| b88816706b | |||
| 80edaae023 | |||
| 468d7f445d | |||
| 4cc74deece |
@@ -30,6 +30,9 @@ RUN npm install && npm cache clean --force
|
||||
# Copy the rest of the application code
|
||||
COPY . .
|
||||
|
||||
# remove dir src/routes/(docs)
|
||||
RUN rm -rf src/routes/\(docs\)
|
||||
|
||||
# Ensure /app/uploads and /app/database have rw permissions
|
||||
RUN mkdir -p /app/uploads /app/database && \
|
||||
chmod -R 777 /app/uploads /app/database
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Kener - A Sveltekit NodeJS Status Page System
|
||||
description: Kener is an open-source Node.js status page tool, designed to make service monitoring and incident handling a breeze. It offers a sleek and user-friendly interface that simplifies tracking service outages and improves how we communicate during incidents.
|
||||
title: Kener Documentation
|
||||
description: Kener is a feature-rich and modern status page system built with SvelteKit and NodeJS. It is open-source and free to use.
|
||||
---
|
||||
|
||||
# Kener - A Feature Rich & Modern Status Page
|
||||
|
||||
+3
-3
@@ -59,7 +59,7 @@ Copy and update the translation file in the `locales` folder. The translation fi
|
||||
"MONITORING": "MONITORING",
|
||||
"No Data": "No Data",
|
||||
"No Incidents": "No Incidents",
|
||||
"No Incident On %date": "No Incident On %date",
|
||||
"No Incident in %date": "No Incident in %date",
|
||||
"No Monitor Found": "No Monitor Found",
|
||||
"No Updates Yet": "No Updates Yet",
|
||||
"Ongoing Incidents": "Ongoing Incidents",
|
||||
@@ -69,8 +69,8 @@ Copy and update the translation file in the `locales` folder. The translation fi
|
||||
"Share": "Share",
|
||||
"Share this monitor using a link with others": "Share this monitor using a link with others",
|
||||
"Standard": "Standard",
|
||||
"Started about %startedAt ago, lasted for about %lastedFor": "Started about %startedAt ago, lasted for about %lastedFor",
|
||||
"Started about %startedAt ago, still ongoing": "Started about %startedAt ago, still ongoing",
|
||||
"Started about %startedAt, lasted for about %lastedFor": "Started about %startedAt, lasted for about %lastedFor",
|
||||
"Started about %startedAt, still ongoing": "Started about %startedAt, still ongoing",
|
||||
"Starts in %startedAt": "Starts in %startedAt",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "Starts in %startedAt, will last for about %lastedFor",
|
||||
"Status": "Status",
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ description: Roadmap for Kener
|
||||
|
||||
☑ ~~Handle uploaded images for docker containers~~
|
||||
|
||||
☐ Introduce sitemap.xml
|
||||
☑ ~~Introduce sitemap.xml~~
|
||||
|
||||
☑ ~~Migrate from moment to date-fns for status page~~ (moment remains in dashboard. Will remove later)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import dotenv from "dotenv";
|
||||
dotenv.config();
|
||||
import express from "express";
|
||||
import Startup from "./src/lib/server/startup.js";
|
||||
import { GetSiteMap } from "./src/lib/server/controllers/controller.js";
|
||||
import fs from "fs-extra";
|
||||
import knex from "knex";
|
||||
import knexOb from "./knexfile.js";
|
||||
@@ -24,6 +25,10 @@ app.use((req, res, next) => {
|
||||
app.get(base + "/healthcheck", (req, res) => {
|
||||
res.end("ok");
|
||||
});
|
||||
app.get(base + "/sitemap.xml", async (req, res) => {
|
||||
res.header("Content-Type", "application/xml");
|
||||
res.send(await GetSiteMap());
|
||||
});
|
||||
//part /uploads server static files from static/uploads
|
||||
|
||||
//set env variable for upload path
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "kener",
|
||||
"version": "3.0.2",
|
||||
"version": "3.0.4",
|
||||
"private": false,
|
||||
"license": "MIT",
|
||||
"description": "Kener: An open-source Node.js status page application for real-time service monitoring, incident management, and customizable reporting. Simplify service outage tracking, enhance incident communication, and ensure a seamless user experience.",
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
>
|
||||
{#if !isFuture && incident.state != "RESOLVED"}
|
||||
<span>
|
||||
{l(lang, "Started about %startedAt ago, still ongoing", {
|
||||
{l(lang, "Started about %startedAt, still ongoing", {
|
||||
startedAt
|
||||
})}
|
||||
</span>
|
||||
@@ -53,7 +53,7 @@
|
||||
<span>
|
||||
{l(
|
||||
lang,
|
||||
"Started about %startedAt ago, lasted for about %lastedFor",
|
||||
"Started about %startedAt, lasted for about %lastedFor",
|
||||
{ startedAt, lastedFor }
|
||||
)}
|
||||
</span>
|
||||
|
||||
@@ -169,10 +169,7 @@
|
||||
{l(lang, "Embed")}
|
||||
</h2>
|
||||
<p class="mb-1 text-xs text-muted-foreground">
|
||||
{@html l(
|
||||
lang,
|
||||
"Embed this moni2tor using <script> or <iframe> in your app."
|
||||
)}
|
||||
{l(lang, "Embed this monitor using <script> or <iframe> in your app.")}
|
||||
</p>
|
||||
<div class="mb-4 grid grid-cols-2 gap-2">
|
||||
<div class="col-span-1">
|
||||
|
||||
@@ -27,15 +27,8 @@ const fdm = function (duration, locale) {
|
||||
};
|
||||
|
||||
const l = function (sessionLangMap, key, args = {}) {
|
||||
const keys = key.split(".");
|
||||
let obj = sessionLangMap;
|
||||
let obj = sessionLangMap[key];
|
||||
|
||||
for (const keyPart of keys) {
|
||||
obj = obj?.[keyPart];
|
||||
if (!obj) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Replace placeholders in the string using the args object
|
||||
if (obj && typeof obj === "string") {
|
||||
obj = obj.replace(/%\w+/g, (placeholder) => {
|
||||
@@ -43,7 +36,6 @@ const l = function (sessionLangMap, key, args = {}) {
|
||||
return args[argKey] !== undefined ? args[argKey] : placeholder;
|
||||
});
|
||||
}
|
||||
|
||||
return obj || key;
|
||||
};
|
||||
const summaryTime = function (summaryStatus) {
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"MONITORING": "ÜBERWACHUNG",
|
||||
"No Data": "Keine Daten",
|
||||
"No Incidents": "Keine Vorfälle",
|
||||
"No Incident On %date": "Kein Vorfall am %date",
|
||||
"No Incident in %date": "Kein Vorfall am %date",
|
||||
"No Monitor Found": "Kein Monitor gefunden",
|
||||
"No Updates Yet": "Noch keine Updates",
|
||||
"Ongoing Incidents": "Laufende Vorfälle",
|
||||
@@ -40,8 +40,8 @@
|
||||
"Share": "Teilen",
|
||||
"Share this monitor using a link with others": "Teilen Sie diesen Monitor mit einem Link mit anderen",
|
||||
"Standard": "Standard",
|
||||
"Started about %startedAt ago, lasted for about %lastedFor": "Begann vor etwa %startedAt und dauerte etwa %lastedFor",
|
||||
"Started about %startedAt ago, still ongoing": "Begann vor etwa %startedAt und dauert noch an",
|
||||
"Started about %startedAt, lasted for about %lastedFor": "Begann vor etwa %startedAt und dauerte etwa %lastedFor",
|
||||
"Started about %startedAt, still ongoing": "Begann vor etwa %startedAt und dauert noch an",
|
||||
"Starts in %startedAt": "Beginnt in %startedAt",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "Beginnt in %startedAt und wird etwa %lastedFor dauern",
|
||||
"Status": "Status",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"MONITORING": "OVERVÅGNING",
|
||||
"No Data": "Ingen Data",
|
||||
"No Incidents": "Ingen Hændelser",
|
||||
"No Incident On %date": "Ingen Hændelse Den %date",
|
||||
"No Incident in %date": "Ingen Hændelse Den %date",
|
||||
"No Monitor Found": "Ingen Monitor Fundet",
|
||||
"No Updates Yet": "Ingen Opdateringer Endnu",
|
||||
"Ongoing Incidents": "Igangværende Hændelser",
|
||||
@@ -40,8 +40,8 @@
|
||||
"Share": "Del",
|
||||
"Share this monitor using a link with others": "Del denne monitor ved hjælp af et link med andre",
|
||||
"Standard": "Standard",
|
||||
"Started about %startedAt ago, lasted for about %lastedFor": "Startede for cirka %startedAt siden, varede i cirka %lastedFor",
|
||||
"Started about %startedAt ago, still ongoing": "Startede for cirka %startedAt siden, stadig igangværende",
|
||||
"Started about %startedAt, lasted for about %lastedFor": "Startede for cirka %startedAt siden, varede i cirka %lastedFor",
|
||||
"Started about %startedAt, still ongoing": "Startede for cirka %startedAt siden, stadig igangværende",
|
||||
"Starts in %startedAt": "Starter om %startedAt",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "Starter om %startedAt, vil vare i cirka %lastedFor",
|
||||
"Status": "Status",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"MONITORING": "MONITORING",
|
||||
"No Data": "No Data",
|
||||
"No Incidents": "No Incidents",
|
||||
"No Incident On %date": "No Incident On %date",
|
||||
"No Incident in %date": "No Incident in %date",
|
||||
"No Monitor Found": "No Monitor Found",
|
||||
"No Updates Yet": "No Updates Yet",
|
||||
"Ongoing Incidents": "Ongoing Incidents",
|
||||
@@ -40,10 +40,10 @@
|
||||
"Share": "Share",
|
||||
"Share this monitor using a link with others": "Share this monitor using a link with others",
|
||||
"Standard": "Standard",
|
||||
"Started about %startedAt ago, lasted for about %lastedFor": "Started about %startedAt ago, lasted for about %lastedFor",
|
||||
"Started about %startedAt ago, still ongoing": "Started about %startedAt ago, still ongoing",
|
||||
"Started about %startedAt, lasted for about %lastedFor": "Started %startedAt, lasted for about %lastedFor",
|
||||
"Started about %startedAt, still ongoing": "Started %startedAt, still ongoing",
|
||||
"Starts in %startedAt": "Starts in %startedAt",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "Starts in %startedAt, will last for about %lastedFor",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "Starts in %startedAt, will last for %lastedFor",
|
||||
"Status": "Status",
|
||||
"Status OK": "Status OK",
|
||||
"Theme": "Theme",
|
||||
@@ -52,4 +52,4 @@
|
||||
"Updates": "Updates",
|
||||
"Uptime": "Uptime",
|
||||
"%status for %duration": "%status for %duration"
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@
|
||||
"MONITORING": "En surveillance",
|
||||
"No Data": "Pas de données",
|
||||
"No Incidents": "Pas d'incidents",
|
||||
"No Incident On %date": "Pas d'incident le %date",
|
||||
"No Incident in %date": "Pas d'incident le %date",
|
||||
"No Monitor Found": "Aucun moniteur trouvé",
|
||||
"No Updates Yet": "Pas encore de mises à jour",
|
||||
"Ongoing Incidents": "Incidents en cours",
|
||||
@@ -40,8 +40,8 @@
|
||||
"Share": "Partager",
|
||||
"Share this monitor using a link with others": "Partagez ce moniteur avec un lien à d'autres personnes",
|
||||
"Standard": "Standard",
|
||||
"Started about %startedAt ago, lasted for about %lastedFor": "Commencé il y a environ %startedAt, a duré environ %lastedFor",
|
||||
"Started about %startedAt ago, still ongoing": "Commencé il y a environ %startedAt, toujours en cours",
|
||||
"Started about %startedAt, lasted for about %lastedFor": "Commencé il y a environ %startedAt, a duré environ %lastedFor",
|
||||
"Started about %startedAt, still ongoing": "Commencé il y a environ %startedAt, toujours en cours",
|
||||
"Starts in %startedAt": "Commence dans %startedAt",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "Commence dans %startedAt, durera environ %lastedFor",
|
||||
"Status": "Statut",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"MONITORING": "निगरानी",
|
||||
"No Data": "कोई डेटा नहीं",
|
||||
"No Incidents": "कोई घटना नहीं",
|
||||
"No Incident On %date": "%date को कोई घटना नहीं",
|
||||
"No Incident in %date": "%date को कोई घटना नहीं",
|
||||
"No Monitor Found": "कोई मॉनिटर नहीं मिला",
|
||||
"No Updates Yet": "अभी तक कोई अपडेट नहीं",
|
||||
"Ongoing Incidents": "चल रही घटनाएँ",
|
||||
@@ -40,8 +40,8 @@
|
||||
"Share": "साझा करें",
|
||||
"Share this monitor using a link with others": "इस मॉनिटर को दूसरों के साथ लिंक के माध्यम से साझा करें",
|
||||
"Standard": "मानक",
|
||||
"Started about %startedAt ago, lasted for about %lastedFor": "लगभग %startedAt पहले शुरू हुआ, लगभग %lastedFor तक चला",
|
||||
"Started about %startedAt ago, still ongoing": "लगभग %startedAt पहले शुरू हुआ, अभी भी जारी है",
|
||||
"Started about %startedAt, lasted for about %lastedFor": "लगभग %startedAt पहले शुरू हुआ, लगभग %lastedFor तक चला",
|
||||
"Started about %startedAt, still ongoing": "लगभग %startedAt पहले शुरू हुआ, अभी भी जारी है",
|
||||
"Starts in %startedAt": "%startedAt में शुरू होगा",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "%startedAt में शुरू होगा, लगभग %lastedFor तक चलेगा",
|
||||
"Status": "स्थिति",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"MONITORING": "モニタリング中",
|
||||
"No Data": "データなし",
|
||||
"No Incidents": "インシデントなし",
|
||||
"No Incident On %date": "%date にインシデントなし",
|
||||
"No Incident in %date": "%date にインシデントなし",
|
||||
"No Monitor Found": "モニターが見つかりません",
|
||||
"No Updates Yet": "まだ更新はありません",
|
||||
"Ongoing Incidents": "進行中のインシデント",
|
||||
@@ -40,8 +40,8 @@
|
||||
"Share": "共有",
|
||||
"Share this monitor using a link with others": "このモニターをリンクで他の人と共有",
|
||||
"Standard": "標準",
|
||||
"Started about %startedAt ago, lasted for about %lastedFor": "%startedAt 前に開始し、約 %lastedFor 続きました",
|
||||
"Started about %startedAt ago, still ongoing": "%startedAt 前に開始し、まだ進行中です",
|
||||
"Started about %startedAt, lasted for about %lastedFor": "%startedAt 前に開始し、約 %lastedFor 続きました",
|
||||
"Started about %startedAt, still ongoing": "%startedAt 前に開始し、まだ進行中です",
|
||||
"Starts in %startedAt": "%startedAt 後に開始",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "%startedAt 後に開始し、約 %lastedFor 続きます",
|
||||
"Status": "ステータス",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"MONITORING": "감시 중",
|
||||
"No Data": "데이터 없음",
|
||||
"No Incidents": "사건 없음",
|
||||
"No Incident On %date": "%date 에는 아무 사건도 없었음",
|
||||
"No Incident in %date": "%date 에는 아무 사건도 없었음",
|
||||
"No Monitor Found": "모니터링 항목을 찾을 수 없음",
|
||||
"No Updates Yet": "아직 아무 업데이트도 없음",
|
||||
"Ongoing Incidents": "진행중 사건",
|
||||
@@ -40,8 +40,8 @@
|
||||
"Share": "공유",
|
||||
"Share this monitor using a link with others": "링크를 사용하여 다른 사람들과 이 모니터링 데이터를 공유해보세요",
|
||||
"Standard": "기본",
|
||||
"Started about %startedAt ago, lasted for about %lastedFor": "%startedAt 전에 시작되었으며, %lastedFor 동안 지속되었습니다",
|
||||
"Started about %startedAt ago, still ongoing": "%startedAt 전에 시작되었으며, 아직 진행중입니다",
|
||||
"Started about %startedAt, lasted for about %lastedFor": "%startedAt 전에 시작되었으며, %lastedFor 동안 지속되었습니다",
|
||||
"Started about %startedAt, still ongoing": "%startedAt 전에 시작되었으며, 아직 진행중입니다",
|
||||
"Starts in %startedAt": "%startedAt 에 시작되었습니다",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "%startedAt 전에 시작되었으며, %lastedFor 까지 지속될 예정입니다",
|
||||
"Status": "상태",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"MONITORING": "MONITOREN",
|
||||
"No Data": "Geen gegevens",
|
||||
"No Incidents": "Geen incidenten",
|
||||
"No Incident On %date": "Geen incident op %date",
|
||||
"No Incident in %date": "Geen incident op %date",
|
||||
"No Monitor Found": "Geen monitor gevonden",
|
||||
"No Updates Yet": "Nog geen updates",
|
||||
"Ongoing Incidents": "Lopende incidenten",
|
||||
@@ -40,8 +40,8 @@
|
||||
"Share": "Delen",
|
||||
"Share this monitor using a link with others": "Deel deze monitor met anderen via een link",
|
||||
"Standard": "Standaard",
|
||||
"Started about %startedAt ago, lasted for about %lastedFor": "Begonnen ongeveer %startedAt geleden, duurde ongeveer %lastedFor",
|
||||
"Started about %startedAt ago, still ongoing": "Begonnen ongeveer %startedAt geleden, nog steeds bezig",
|
||||
"Started about %startedAt, lasted for about %lastedFor": "Begonnen ongeveer %startedAt geleden, duurde ongeveer %lastedFor",
|
||||
"Started about %startedAt, still ongoing": "Begonnen ongeveer %startedAt geleden, nog steeds bezig",
|
||||
"Starts in %startedAt": "Begint over %startedAt",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "Begint over %startedAt, zal ongeveer %lastedFor duren",
|
||||
"Status": "Status",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"MONITORING": "MONITORANDO",
|
||||
"No Data": "Sem dados",
|
||||
"No Incidents": "Sem Incidentes",
|
||||
"No Incident On %date": "Nenhum incidente em %date",
|
||||
"No Incident in %date": "Nenhum incidente em %date",
|
||||
"No Monitor Found": "Nenhum monitor encontrado",
|
||||
"No Updates Yet": "Nenhuma atualização ainda",
|
||||
"Ongoing Incidents": "Incidentes em Andamento",
|
||||
@@ -40,8 +40,8 @@
|
||||
"Share": "Compartilhar",
|
||||
"Share this monitor using a link with others": "Compartilhar este monitor através do link",
|
||||
"Standard": "Padrão",
|
||||
"Started about %startedAt ago, lasted for about %lastedFor": "Iniciado há cerca de %startedAt e durou aproximadamente %lastedFor",
|
||||
"Started about %startedAt ago, still ongoing": "Iniciado há cerca de %startedAt, ainda em andamento",
|
||||
"Started about %startedAt, lasted for about %lastedFor": "Iniciado há cerca de %startedAt e durou aproximadamente %lastedFor",
|
||||
"Started about %startedAt, still ongoing": "Iniciado há cerca de %startedAt, ainda em andamento",
|
||||
"Starts in %startedAt": "Inicia em %startedAt",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "Inícia em %startedAt, com duração de aproximadamente %lastedFor",
|
||||
"Status": "Status",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"MONITORING": "МОНИТОРИНГ",
|
||||
"No Data": "Нет данных",
|
||||
"No Incidents": "Нет инцидентов",
|
||||
"No Incident On %date": "Нет инцидентов на %date",
|
||||
"No Incident in %date": "Нет инцидентов на %date",
|
||||
"No Monitor Found": "Монитор не найден",
|
||||
"No Updates Yet": "Пока нет обновлений",
|
||||
"Ongoing Incidents": "Текущие инциденты",
|
||||
@@ -40,8 +40,8 @@
|
||||
"Share": "Поделиться",
|
||||
"Share this monitor using a link with others": "Поделитесь этим монитором с другими по ссылке",
|
||||
"Standard": "Стандартная",
|
||||
"Started about %startedAt ago, lasted for about %lastedFor": "Началось около %startedAt назад, длилось около %lastedFor",
|
||||
"Started about %startedAt ago, still ongoing": "Началось около %startedAt назад, все еще продолжается",
|
||||
"Started about %startedAt, lasted for about %lastedFor": "Началось около %startedAt назад, длилось около %lastedFor",
|
||||
"Started about %startedAt, still ongoing": "Началось около %startedAt назад, все еще продолжается",
|
||||
"Starts in %startedAt": "Начнется через %startedAt",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "Начнется через %startedAt, продлится около %lastedFor",
|
||||
"Status": "Статус",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"MONITORING": "Đang giám sát",
|
||||
"No Data": "Không có dữ liệu",
|
||||
"No Incidents": "Không có sự cố",
|
||||
"No Incident On %date": "Không có sự cố vào %date",
|
||||
"No Incident in %date": "Không có sự cố vào %date",
|
||||
"No Monitor Found": "Không tìm thấy trình theo dõi",
|
||||
"No Updates Yet": "Chưa có cập nhật",
|
||||
"Ongoing Incidents": "Sự cố đang diễn ra",
|
||||
@@ -40,8 +40,8 @@
|
||||
"Share": "Chia sẻ",
|
||||
"Share this monitor using a link with others": "Chia sẻ trình theo dõi này với người khác bằng liên kết",
|
||||
"Standard": "Tiêu chuẩn",
|
||||
"Started about %startedAt ago, lasted for about %lastedFor": "Bắt đầu khoảng %startedAt trước, kéo dài khoảng %lastedFor",
|
||||
"Started about %startedAt ago, still ongoing": "Bắt đầu khoảng %startedAt trước, vẫn đang diễn ra",
|
||||
"Started about %startedAt, lasted for about %lastedFor": "Bắt đầu khoảng %startedAt trước, kéo dài khoảng %lastedFor",
|
||||
"Started about %startedAt, still ongoing": "Bắt đầu khoảng %startedAt trước, vẫn đang diễn ra",
|
||||
"Starts in %startedAt": "Bắt đầu trong %startedAt",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "Bắt đầu trong %startedAt, sẽ kéo dài khoảng %lastedFor",
|
||||
"Status": "Trạng thái",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"MONITORING": "正在监控",
|
||||
"No Data": "无数据",
|
||||
"No Incidents": "无事件",
|
||||
"No Incident On %date": "%date 无事件",
|
||||
"No Incident in %date": "%date 无事件",
|
||||
"No Monitor Found": "未找到监控",
|
||||
"No Updates Yet": "尚无更新",
|
||||
"Ongoing Incidents": "正在处理的事件",
|
||||
@@ -40,8 +40,8 @@
|
||||
"Share": "分享",
|
||||
"Share this monitor using a link with others": "通过链接与他人分享此监控",
|
||||
"Standard": "标准",
|
||||
"Started about %startedAt ago, lasted for about %lastedFor": "大约 %startedAt 前开始,持续了约 %lastedFor",
|
||||
"Started about %startedAt ago, still ongoing": "大约 %startedAt 前开始,目前仍在进行中",
|
||||
"Started about %startedAt, lasted for about %lastedFor": "大约 %startedAt 前开始,持续了约 %lastedFor",
|
||||
"Started about %startedAt, still ongoing": "大约 %startedAt 前开始,目前仍在进行中",
|
||||
"Starts in %startedAt": "%startedAt 后开始",
|
||||
"Starts in %startedAt, will last for about %lastedFor": "%startedAt 后开始,将持续约 %lastedFor",
|
||||
"Status": "状态",
|
||||
|
||||
@@ -16,6 +16,7 @@ import db from "../db/db.js";
|
||||
import bcrypt from "bcrypt";
|
||||
import jwt from "jsonwebtoken";
|
||||
import crypto from "crypto";
|
||||
import { format, subMonths, addMonths, startOfMonth } from "date-fns";
|
||||
|
||||
const saltRounds = 10;
|
||||
const DUMMY_SECRET = "DUMMY_SECRET";
|
||||
@@ -398,8 +399,13 @@ export const InterpolateData = (data, start, anchorStatus, e) => {
|
||||
if (e) {
|
||||
end = e;
|
||||
}
|
||||
let dataMap = data.reduce((acc, d) => {
|
||||
acc[d.timestamp] = d;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
for (let i = start; i <= end; i += 60) {
|
||||
let nowData = data.find((d) => d.timestamp === i);
|
||||
let nowData = dataMap[i];
|
||||
if (!!nowData) {
|
||||
status = nowData.status;
|
||||
}
|
||||
@@ -800,3 +806,93 @@ export const IsLoggedInSession = async (cookies) => {
|
||||
user: userDB
|
||||
};
|
||||
};
|
||||
|
||||
export const GetSiteMap = async (cookies) => {
|
||||
let siteMapData = [];
|
||||
let siteURLData = await GetSiteDataByKey("siteURL");
|
||||
let categories = await GetSiteDataByKey("categories");
|
||||
let navs = await GetSiteDataByKey("nav");
|
||||
if (!!siteURLData) {
|
||||
siteMapData.push({
|
||||
url: siteURLData,
|
||||
lastmod: new Date().toISOString(),
|
||||
priority: 1
|
||||
});
|
||||
}
|
||||
|
||||
//get today's date in January-2025 format date-fns
|
||||
const today = format(new Date(), "MMMM-yyyy");
|
||||
//last month
|
||||
const lastMonth = format(subMonths(new Date(), 1), "MMMM-yyyy", { addMonths: -1 });
|
||||
const nextMonth = format(addMonths(new Date(), 1), "MMMM-yyyy", { addMonths: -1 });
|
||||
|
||||
siteMapData.push({
|
||||
url: siteURLData + "/incidents/" + today,
|
||||
lastmod: startOfMonth(new Date()).toISOString(),
|
||||
priority: 0.9
|
||||
});
|
||||
siteMapData.push({
|
||||
url: siteURLData + "/incidents/" + lastMonth,
|
||||
lastmod: startOfMonth(new Date()).toISOString(),
|
||||
priority: 0.9
|
||||
});
|
||||
siteMapData.push({
|
||||
url: siteURLData + "/incidents/" + nextMonth,
|
||||
lastmod: startOfMonth(new Date()).toISOString(),
|
||||
priority: 0.9
|
||||
});
|
||||
|
||||
if (!!categories) {
|
||||
for (let i = 0; i < categories.length; i++) {
|
||||
if (categories[i].name !== "Home") {
|
||||
siteMapData.push({
|
||||
url: siteURLData + "?category=" + categories[i].name,
|
||||
lastmod: new Date().toISOString(),
|
||||
priority: 0.9
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!!navs) {
|
||||
for (let i = 0; i < navs.length; i++) {
|
||||
if (navs[i].url.startsWith(siteURLData)) {
|
||||
siteMapData.push({
|
||||
url: navs[i].url,
|
||||
lastmod: new Date().toISOString(),
|
||||
priority: 0.9
|
||||
});
|
||||
} else if (navs[i].url.startsWith("/")) {
|
||||
siteMapData.push({
|
||||
url: siteURLData + navs[i].url,
|
||||
lastmod: new Date().toISOString(),
|
||||
priority: 0.9
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let monitors = await GetMonitors({ status: "ACTIVE" });
|
||||
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
siteMapData.push({
|
||||
url: siteURLData + "?monitor=" + monitors[i].tag,
|
||||
lastmod: new Date(monitors[i].updated_at).toISOString(),
|
||||
priority: 0.8
|
||||
});
|
||||
}
|
||||
|
||||
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
${siteMapData
|
||||
.map(
|
||||
(page) => `
|
||||
<url>
|
||||
<loc>${page.url}</loc>
|
||||
<lastmod>${page.lastmod}</lastmod>
|
||||
<priority>${page.priority}</priority>
|
||||
</url>
|
||||
`
|
||||
)
|
||||
.join("")}
|
||||
</urlset>`;
|
||||
};
|
||||
|
||||
@@ -342,7 +342,7 @@ const Minuter = async (monitor) => {
|
||||
realTimeData[startOfMinute] = apiResponse;
|
||||
if (apiResponse.type === TIMEOUT) {
|
||||
apiQueue.push(async (cb) => {
|
||||
await Wait(4000);
|
||||
await Wait(500); //wait for 500ms
|
||||
console.log(
|
||||
"Retrying api call for " +
|
||||
monitor.name +
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
|
||||
<svelte:window on:pagechange={pageChange} on:rightbar={updateTableOfContents} />
|
||||
<svelte:head>
|
||||
<title>Kener Documentation</title>
|
||||
<link rel="icon" id="kener-app-favicon" href="{base}/logo96.png" />
|
||||
|
||||
<!-- Google tag (gtag.js) -->
|
||||
@@ -86,7 +87,7 @@
|
||||
<img src="https://kener.ing/logo.png" class="h-8 w-8" alt="" />
|
||||
<span class="text-xl font-medium">Kener Documentation</span>
|
||||
<span class="me-2 rounded border px-2.5 py-0.5 text-xs font-medium">
|
||||
v3.0.2
|
||||
v3.0.4
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -6,11 +6,12 @@ import moment from "moment";
|
||||
|
||||
export async function load({ parent, url }) {
|
||||
let monitors = await GetMonitors({ status: "ACTIVE" });
|
||||
|
||||
const query = url.searchParams;
|
||||
const requiredCategory = query.get("category") || "Home";
|
||||
const parentData = await parent();
|
||||
const siteData = parentData.site;
|
||||
let pageTitle = siteData.title;
|
||||
let pageDescription = "";
|
||||
monitors = SortMonitor(siteData.monitorSort, monitors);
|
||||
const monitorsActive = [];
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
@@ -51,6 +52,19 @@ export async function load({ parent, url }) {
|
||||
//if not home page
|
||||
let isCategoryPage = !!query.get("category") && query.get("category") !== "Home";
|
||||
let isMonitorPage = !!query.get("monitor");
|
||||
if (isMonitorPage && monitorsActive.length > 0) {
|
||||
pageTitle = monitorsActive[0].name + " - " + pageTitle;
|
||||
pageDescription = monitorsActive[0].description;
|
||||
}
|
||||
//if category page
|
||||
if (isCategoryPage) {
|
||||
let allCategories = siteData.categories;
|
||||
let selectedCategory = allCategories.find((category) => category.name === requiredCategory);
|
||||
if (selectedCategory) {
|
||||
pageTitle = selectedCategory.name + " - " + pageTitle;
|
||||
pageDescription = selectedCategory.description;
|
||||
}
|
||||
}
|
||||
if (isCategoryPage || isMonitorPage) {
|
||||
let eligibleTags = monitorsActive.map((monitor) => monitor.tag);
|
||||
//filter incidents that have monitor_tag in monitors
|
||||
@@ -85,11 +99,14 @@ export async function load({ parent, url }) {
|
||||
return incident;
|
||||
});
|
||||
let unresolvedIncidents = allOpenIncidents.filter((incident) => incident.state !== "RESOLVED");
|
||||
|
||||
return {
|
||||
monitors: monitorsActive,
|
||||
unresolvedIncidents: allOpenIncidents,
|
||||
categoryName: requiredCategory,
|
||||
isCategoryPage: isCategoryPage,
|
||||
isMonitorPage: isMonitorPage
|
||||
isMonitorPage: isMonitorPage,
|
||||
pageTitle: pageTitle,
|
||||
pageDescription: pageDescription
|
||||
};
|
||||
}
|
||||
|
||||
@@ -34,8 +34,10 @@
|
||||
|
||||
if (data.isCategoryPage) {
|
||||
let category = data.site.categories.find((e) => e.name == data.categoryName);
|
||||
data.site.hero.title = category.name;
|
||||
data.site.hero.subtitle = category.description;
|
||||
if (!!category) {
|
||||
data.site.hero.title = category.name;
|
||||
data.site.hero.subtitle = category.description;
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
@@ -43,6 +45,12 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{data.pageTitle}</title>
|
||||
{#if !!data.pageDescription}
|
||||
<meta name="description" content={data.pageDescription} />
|
||||
{/if}
|
||||
</svelte:head>
|
||||
<div class="mt-12"></div>
|
||||
{#if data.site.hero && !data.isMonitorPage}
|
||||
<section
|
||||
@@ -183,7 +191,7 @@
|
||||
window.location.href = `?category=${category.name}`;
|
||||
}}
|
||||
>
|
||||
<Card.Root class="hover:bg-secondary">
|
||||
<Card.Root class="mb-4 hover:bg-secondary">
|
||||
<Card.Header class="bounce-right relative w-full cursor-pointer px-4 ">
|
||||
<Card.Title class="w-full ">
|
||||
{category.name}
|
||||
|
||||
@@ -50,6 +50,13 @@
|
||||
let sortedIncidentSmartDates = Object.keys(incidentSmartDates).sort((a, b) => a - b);
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>
|
||||
{f(parse(data.thisMonthName, "MMMM-yyyy", new Date()), "MMMM, yyyy", selectedLang)}
|
||||
{l(data.lang, "Incident Updates")} |
|
||||
{data.site.title}
|
||||
</title>
|
||||
</svelte:head>
|
||||
<div class="mt-12"></div>
|
||||
<section class="mx-auto my-2 flex w-full max-w-[655px] flex-1 flex-col items-start justify-center">
|
||||
<Button
|
||||
@@ -98,7 +105,7 @@
|
||||
</div>
|
||||
|
||||
<h1 class=" text-xl font-semibold leading-tight">
|
||||
{l(data.lang, "No Incident On %date", {
|
||||
{l(data.lang, "No Incident in %date", {
|
||||
date: data.thisMonthName.replace("-", ", ")
|
||||
})}
|
||||
</h1>
|
||||
|
||||
Reference in New Issue
Block a user