fancy-gatus/src/routes/+page.svelte

123 lines
3.7 KiB
Svelte

<script lang="ts">
import axios from 'axios'
import { onMount } from 'svelte'
import type { Config } from '$lib/types/config'
import type { Status } from '$lib/types/api'
import Loader from '$lib/components/Loader.svelte'
import Header from '$lib/components/Header.svelte'
import Notice from '$lib/components/Notice.svelte'
import OverallStatus from '$lib/components/OverallStatus.svelte'
import EndpointGroup from '$lib/components/StatusGroup.svelte'
import RefreshSettings from '$lib/components/RefreshSettings.svelte'
import Footer from '$lib/components/Footer.svelte'
let loading = $state(true)
let config: Config = $state({})
let apiData: Status[] = $state([])
function getConfig() {
axios
.get('config.json', { baseURL: '/' })
.then((response) => {
config = response.data
// Set title if defined in config
if (config.title) {
document.title = config.title
}
getApiData()
})
.catch((error) => {
if (error.response.status === 404) {
console.warn('No config.json file found. Using default values.')
getApiData()
} else {
console.log('Error getting config: ' + error)
}
})
}
function getApiData() {
// Set base URL for API calls if defined in config
if (config.gatusBaseUrl && axios.defaults.baseURL !== config.gatusBaseUrl) {
axios.defaults.baseURL = config.gatusBaseUrl
}
axios
.get('/api/v1/endpoints/statuses')
.then((response) => {
apiData = response.data
loading = false
})
.catch((error) => {
console.log(error)
})
}
// Group statuses by their group name
// and sort them according to the config if specified
let groups: { title: string; statuses: Status[] }[] = $derived.by(() => {
// Group statuses by group name
let groups: Map<string, Status[]> = new Map<string, Status[]>()
apiData.map((status) => {
// Filter statuses that should be hidden
if (config.hiddenStatuses?.includes(status.name)) return
if (!status.group) {
status.group = 'Ungrouped'
}
// Filter groups that should be hidden
if (config.hiddenGroups?.includes(status.group)) return
let groupStatuses = groups.get(status.group) || []
groupStatuses.push(status)
groups.set(status.group, groupStatuses)
})
// Sort by config
let tmp = groups
let sortedGroups: { title: string; statuses: Status[] }[] = []
if (config.groupOrder) {
config.groupOrder.forEach((key) => {
if (tmp.has(key)) {
sortedGroups.push({ title: key, statuses: tmp.get(key)! })
tmp.delete(key)
}
})
}
// Sort remaining group alphabetically
let sortedKeys = [...tmp.keys()].sort((a, b) => a.localeCompare(b))
sortedKeys.map((key) => {
let statuses = tmp.get(key)!
sortedGroups.push({ title: key, statuses })
})
return sortedGroups
})
// Array of statuses where the last result has success = false
let failedStatuses = $derived.by(() => {
return apiData.filter((status) => {
return !status.results[status.results.length - 1].success
})
})
onMount(() => {
getConfig()
})
</script>
{#if loading}
<Loader />
{:else}
<Header title={config.title} />
{#if config.notice}
<Notice notice={config.notice} />
{/if}
<OverallStatus {failedStatuses} />
{#each groups as group (group.title)}
<EndpointGroup
title={group.title}
statuses={group.statuses}
expandByDefault={config.defaultExpandGroups}
/>
{/each}
<RefreshSettings defaultRefreshInterval={config.defaultRefreshInterval} onRefresh={getConfig} />
<Footer />
{/if}