Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion web/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"eslintConfig": {
"root": true,
"env": {
"node": true
"node": true,
"es2024": true
Copy link
Contributor Author

@PythonGermany PythonGermany Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about this yet. Without this eslint complains about globalThis not being defined. But I still haven't understood the impact of the change and which version to choose.

},
"extends": [
"plugin:vue/vue3-essential",
Expand Down
25 changes: 21 additions & 4 deletions web/app/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,37 @@
<html lang="en" class="{{ .Theme }}">
<head>
<meta charset="utf-8" />
<title>{{ .UI.Title }}</title>
<script type="text/javascript">
window.config = {logo: "{{ .UI.Logo }}", header: "{{ .UI.Header }}", dashboardHeading: "{{ .UI.DashboardHeading }}", dashboardSubheading: "{{ .UI.DashboardSubheading }}", link: "{{ .UI.Link }}", buttons: [], maximumNumberOfResults: "{{ .UI.MaximumNumberOfResults }}", defaultSortBy: "{{ .UI.DefaultSortBy }}", defaultFilterBy: "{{ .UI.DefaultFilterBy }}"};{{- range .UI.Buttons}}window.config.buttons.push({name:"{{ .Name }}",link:"{{ .Link }}"});{{end}}
// Initialize theme immediately to prevent flash
(function() {
// String is percent-encoded to prevent it from being replaced when ui config is injected
if (document.title !== decodeURIComponent("%7B%7B%20.UI.Title%20%7D%7D")) {
globalThis.config = {
logo: "{{ .UI.Logo }}",
header: "{{ .UI.Header }}",
dashboardHeading: "{{ .UI.DashboardHeading }}",
dashboardSubheading: "{{ .UI.DashboardSubheading }}",
link: "{{ .UI.Link }}",
buttons: [],
maximumNumberOfResults: "{{ .UI.MaximumNumberOfResults }}",
defaultSortBy: "{{ .UI.DefaultSortBy }}",
defaultFilterBy: "{{ .UI.DefaultFilterBy }}"
};
{{- range .UI.Buttons}}globalThis.config.buttons.push({name:"{{ .Name }}",link:"{{ .Link }}"});{{end}}
} else {
console.warn('Running in development mode; UI configuration is not injected.');
document.title= 'Gatus (Development)';
}
// Initialize theme immediately to prevent flash
const themeFromCookie = document.cookie.match(/theme=(dark|light);?/)?.[1];
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const prefersDark = globalThis.matchMedia('(prefers-color-scheme: dark)').matches;
if (themeFromCookie === 'dark' || (!themeFromCookie && prefersDark)) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
})();
</script>
<title>{{ .UI.Title }}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
Expand Down
16 changes: 4 additions & 12 deletions web/app/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -176,21 +176,13 @@ const tooltipIsPersistent = ref(false)
let configInterval = null

// Computed properties
const logo = computed(() => {
return window.config && window.config.logo && window.config.logo !== '{{ .UI.Logo }}' ? window.config.logo : ""
})
const logo = computed(() => globalThis.config?.logo ?? "")

const header = computed(() => {
return window.config && window.config.header && window.config.header !== '{{ .UI.Header }}' ? window.config.header : "Gatus"
})
const header = computed(() => globalThis.config?.header ?? "Gatus")

const link = computed(() => {
return window.config && window.config.link && window.config.link !== '{{ .UI.Link }}' ? window.config.link : null
})
const link = computed(() => globalThis.config?.link ?? null)

const buttons = computed(() => {
return window.config && window.config.buttons ? window.config.buttons : []
})
const buttons = computed(() => globalThis.config?.buttons ?? [])

// Methods
const fetchConfig = async () => {
Expand Down
7 changes: 3 additions & 4 deletions web/app/src/components/Pagination.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,9 @@ const currentPage = ref(props.currentPageProp)

const maxPages = computed(() => {
// Use maximumNumberOfResults from config if available, otherwise default to 100
let maxResults = 100 // Default value
// Check if window.config exists and has maximumNumberOfResults
if (typeof window !== 'undefined' && window.config && window.config.maximumNumberOfResults) {
const parsed = parseInt(window.config.maximumNumberOfResults)
let maxResults = 100
if (globalThis.config?.maximumNumberOfResults) {
const parsed = parseInt(globalThis.config.maximumNumberOfResults)
if (!isNaN(parsed)) {
maxResults = parsed
}
Expand Down
4 changes: 2 additions & 2 deletions web/app/src/components/SearchBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ import { Input } from '@/components/ui/input'
import { Select } from '@/components/ui/select'

const searchQuery = ref('')
const filterBy = ref(localStorage.getItem('gatus:filter-by') || (typeof window !== 'undefined' && window.config?.defaultFilterBy) || 'none')
const sortBy = ref(localStorage.getItem('gatus:sort-by') || (typeof window !== 'undefined' && window.config?.defaultSortBy) || 'name')
const filterBy = ref(localStorage.getItem('gatus:filter-by') || globalThis.config?.defaultFilterBy || 'none')
const sortBy = ref(localStorage.getItem('gatus:sort-by') || globalThis.config?.defaultSortBy || 'name')

const filterOptions = [
{ label: 'None', value: 'none' },
Expand Down
8 changes: 2 additions & 6 deletions web/app/src/views/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -532,13 +532,9 @@ const initializeCollapsedGroups = () => {
}
}

const dashboardHeading = computed(() => {
return window.config && window.config.dashboardHeading && window.config.dashboardHeading !== '{{ .UI.DashboardHeading }}' ? window.config.dashboardHeading : "Health Dashboard"
})
const dashboardHeading = computed(() => globalThis.config?.dashboardHeading ?? "Health Dashboard")

const dashboardSubheading = computed(() => {
return window.config && window.config.dashboardSubheading && window.config.dashboardSubheading !== '{{ .UI.DashboardSubheading }}' ? window.config.dashboardSubheading : "Monitor the health of your endpoints in real-time"
})
const dashboardSubheading = computed(() => globalThis.config?.dashboardSubheading ?? "Monitor the health of your endpoints in real-time")

onMounted(() => {
fetchData()
Expand Down
25 changes: 21 additions & 4 deletions web/static/index.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
<!doctype html><html lang="en" class="{{ .Theme }}"><head><meta charset="utf-8"/><script>window.config = {logo: "{{ .UI.Logo }}", header: "{{ .UI.Header }}", dashboardHeading: "{{ .UI.DashboardHeading }}", dashboardSubheading: "{{ .UI.DashboardSubheading }}", link: "{{ .UI.Link }}", buttons: [], maximumNumberOfResults: "{{ .UI.MaximumNumberOfResults }}", defaultSortBy: "{{ .UI.DefaultSortBy }}", defaultFilterBy: "{{ .UI.DefaultFilterBy }}"};{{- range .UI.Buttons}}window.config.buttons.push({name:"{{ .Name }}",link:"{{ .Link }}"});{{end}}
// Initialize theme immediately to prevent flash
(function() {
<!doctype html><html lang="en" class="{{ .Theme }}"><head><meta charset="utf-8"/><title>{{ .UI.Title }}</title><script>(function() {
// String is percent-encoded to prevent it from being replaced when ui config is injected
if (document.title !== decodeURIComponent("%7B%7B%20.UI.Title%20%7D%7D")) {
window.config = {
logo: "{{ .UI.Logo }}",
header: "{{ .UI.Header }}",
dashboardHeading: "{{ .UI.DashboardHeading }}",
dashboardSubheading: "{{ .UI.DashboardSubheading }}",
link: "{{ .UI.Link }}",
buttons: [],
maximumNumberOfResults: "{{ .UI.MaximumNumberOfResults }}",
defaultSortBy: "{{ .UI.DefaultSortBy }}",
defaultFilterBy: "{{ .UI.DefaultFilterBy }}"
};
{{- range .UI.Buttons}}window.config.buttons.push({name:"{{ .Name }}",link:"{{ .Link }}"});{{end}}
} else {
console.warn('Running in development mode; UI configuration is not injected.');
document.title= 'Gatus (Development)';
}
// Initialize theme immediately to prevent flash
const themeFromCookie = document.cookie.match(/theme=(dark|light);?/)?.[1];
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (themeFromCookie === 'dark' || (!themeFromCookie && prefersDark)) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
})();</script><title>{{ .UI.Title }}</title><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width,initial-scale=1"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json" crossorigin="use-credentials"/><link rel="shortcut icon" href="/favicon.ico"/><link rel="stylesheet" href="/css/custom.css"/><meta name="description" content="{{ .UI.Description }}"/><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/><meta name="apple-mobile-web-app-title" content="{{ .UI.Title }}"/><meta name="application-name" content="{{ .UI.Title }}"/><meta name="theme-color" content="#f7f9fb"/><script defer="defer" src="/js/chunk-vendors.js"></script><script defer="defer" src="/js/app.js"></script><link href="/css/app.css" rel="stylesheet"></head><body><noscript><strong>Enable JavaScript to view this page.</strong></noscript><div id="app"></div></body></html>
})();</script><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width,initial-scale=1"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json" crossorigin="use-credentials"/><link rel="shortcut icon" href="/favicon.ico"/><link rel="stylesheet" href="/css/custom.css"/><meta name="description" content="{{ .UI.Description }}"/><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/><meta name="apple-mobile-web-app-title" content="{{ .UI.Title }}"/><meta name="application-name" content="{{ .UI.Title }}"/><meta name="theme-color" content="#f7f9fb"/><script defer="defer" src="/js/chunk-vendors.js"></script><script defer="defer" src="/js/app.js"></script><link href="/css/app.css" rel="stylesheet"></head><body><noscript><strong>Enable JavaScript to view this page.</strong></noscript><div id="app"></div></body></html>
2 changes: 1 addition & 1 deletion web/static/js/app.js

Large diffs are not rendered by default.