mirror of
https://github.com/grafana/grafana.git
synced 2025-02-09 23:16:16 -06:00
Adapt document language HTML "lang" attribute should reflect the actual language used in texts. Important for accessibility functions (screen readers), but also usable in CSS.
357 lines
12 KiB
HTML
357 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="[[.User.Language]]">
|
|
<head>
|
|
[[ if and .CSPEnabled .IsDevelopmentEnv ]]
|
|
<!-- Cypress overwrites CSP headers in HTTP requests, so this is required for e2e tests-->
|
|
<meta http-equiv="Content-Security-Policy" content="[[.CSPContent]]"/>
|
|
[[ end ]]
|
|
<meta charset="utf-8" />
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
|
<meta name="viewport" content="width=device-width" />
|
|
<meta name="theme-color" content="#000" />
|
|
|
|
<title>[[.AppTitle]]</title>
|
|
|
|
<base href="[[.AppSubUrl]]/" />
|
|
|
|
<link rel="icon" type="image/png" href="[[.FavIcon]]" />
|
|
<link rel="apple-touch-icon" sizes="180x180" href="[[.AppleTouchIcon]]" />
|
|
<link rel="mask-icon" href="[[.ContentDeliveryURL]]public/img/grafana_mask_icon.svg" color="#F05A28" />
|
|
|
|
<!-- If theme is "system", we inject the stylesheets with javascript further down the page -->
|
|
[[ if eq .ThemeType "light" ]]
|
|
<link rel="stylesheet" href="[[.ContentDeliveryURL]]public/build/<%= htmlWebpackPlugin.files.cssChunks.light %>" />
|
|
[[ else if eq .ThemeType "dark" ]]
|
|
<link rel="stylesheet" href="[[.ContentDeliveryURL]]public/build/<%= htmlWebpackPlugin.files.cssChunks.dark %>" />
|
|
[[ end ]]
|
|
|
|
<script nonce="[[.Nonce]]">
|
|
performance.mark('frontend_boot_css_time_seconds');
|
|
</script>
|
|
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
|
<meta name="msapplication-TileColor" content="#2b5797" />
|
|
<meta name="msapplication-config" content="public/img/browserconfig.xml" />
|
|
</head>
|
|
|
|
<body class="theme-[[ .ThemeType ]] [[.AppNameBodyClass]]">
|
|
<style>
|
|
.preloader {
|
|
height: 100%;
|
|
flex-direction: column;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.preloader__enter {
|
|
opacity: 0;
|
|
animation-name: preloader-fade-in;
|
|
animation-iteration-count: 1;
|
|
animation-duration: 0.9s;
|
|
animation-delay: 1.35s;
|
|
animation-fill-mode: forwards;
|
|
}
|
|
|
|
.preloader__bounce {
|
|
text-align: center;
|
|
animation-name: preloader-bounce;
|
|
animation-duration: 0.9s;
|
|
animation-iteration-count: infinite;
|
|
}
|
|
|
|
.preloader__logo {
|
|
display: inline-block;
|
|
animation-name: preloader-squash;
|
|
animation-duration: 0.9s;
|
|
animation-iteration-count: infinite;
|
|
width: 60px;
|
|
height: 60px;
|
|
background-repeat: no-repeat;
|
|
background-size: contain;
|
|
background-image: url('[[.LoadingLogo]]');
|
|
}
|
|
|
|
.preloader__text {
|
|
margin-top: 16px;
|
|
font-weight: 500;
|
|
font-size: 14px;
|
|
font-family: Sans-serif;
|
|
opacity: 0;
|
|
animation-name: preloader-fade-in;
|
|
animation-duration: 0.9s;
|
|
animation-delay: 1.8s;
|
|
animation-fill-mode: forwards;
|
|
}
|
|
|
|
.theme-light .preloader__text {
|
|
color: #52545c;
|
|
}
|
|
|
|
.theme-dark .preloader__text {
|
|
color: #d8d9da;
|
|
}
|
|
|
|
@keyframes preloader-fade-in {
|
|
0% {
|
|
opacity: 0;
|
|
/*animation-timing-function: linear;*/
|
|
animation-timing-function: cubic-bezier(0, 0, 0.5, 1);
|
|
}
|
|
100% {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@keyframes preloader-bounce {
|
|
from,
|
|
to {
|
|
transform: translateY(0px);
|
|
animation-timing-function: cubic-bezier(0.3, 0, 0.1, 1);
|
|
}
|
|
50% {
|
|
transform: translateY(-50px);
|
|
animation-timing-function: cubic-bezier(0.9, 0, 0.7, 1);
|
|
}
|
|
}
|
|
|
|
@keyframes preloader-squash {
|
|
0% {
|
|
transform: scaleX(1.3) scaleY(0.8);
|
|
animation-timing-function: cubic-bezier(0.3, 0, 0.1, 1);
|
|
transform-origin: bottom center;
|
|
}
|
|
15% {
|
|
transform: scaleX(0.75) scaleY(1.25);
|
|
animation-timing-function: cubic-bezier(0, 0, 0.7, 0.75);
|
|
transform-origin: bottom center;
|
|
}
|
|
55% {
|
|
transform: scaleX(1.05) scaleY(0.95);
|
|
animation-timing-function: cubic-bezier(0.9, 0, 1, 1);
|
|
transform-origin: top center;
|
|
}
|
|
95% {
|
|
transform: scaleX(0.75) scaleY(1.25);
|
|
animation-timing-function: cubic-bezier(0, 0, 0, 1);
|
|
transform-origin: bottom center;
|
|
}
|
|
100% {
|
|
transform: scaleX(1.3) scaleY(0.8);
|
|
transform-origin: bottom center;
|
|
animation-timing-function: cubic-bezier(0, 0, 0.7, 1);
|
|
}
|
|
}
|
|
|
|
/* Fail info */
|
|
.preloader__text--fail {
|
|
display: none;
|
|
}
|
|
|
|
/* stop logo animation */
|
|
.preloader--done .preloader__bounce,
|
|
.preloader--done .preloader__logo {
|
|
animation-name: none;
|
|
display: none;
|
|
}
|
|
|
|
.preloader--done .preloader__logo,
|
|
.preloader--done .preloader__text {
|
|
display: none;
|
|
color: #ff5705 !important;
|
|
font-size: 15px;
|
|
}
|
|
|
|
.preloader--done .preloader__text--fail {
|
|
display: block;
|
|
}
|
|
|
|
[ng\:cloak],
|
|
[ng-cloak],
|
|
.ng-cloak {
|
|
display: none !important;
|
|
}
|
|
</style>
|
|
|
|
<div class="preloader">
|
|
<div class="preloader__enter">
|
|
<div class="preloader__bounce">
|
|
<div class="preloader__logo"></div>
|
|
</div>
|
|
</div>
|
|
<div class="preloader__text">Loading Grafana</div>
|
|
<div class="preloader__text preloader__text--fail">
|
|
<p>
|
|
<strong>If you're seeing this Grafana has failed to load its application files</strong>
|
|
<br />
|
|
<br />
|
|
</p>
|
|
<p>
|
|
1. This could be caused by your reverse proxy settings.<br /><br />
|
|
2. If you host grafana under subpath make sure your grafana.ini root_url setting includes subpath. If not
|
|
using a reverse proxy make sure to set serve_from_sub_path to true.<br />
|
|
<br />
|
|
3. If you have a local dev build make sure you build frontend using: yarn start, or yarn build<br />
|
|
<br />
|
|
4. Sometimes restarting grafana-server can help<br />
|
|
<br />
|
|
5. Check if you are using a non-supported browser. For more information, refer to the list of
|
|
<a href="https://grafana.com/docs/grafana/latest/installation/requirements/#supported-web-browsers">
|
|
supported browsers</a
|
|
>.
|
|
</p>
|
|
</div>
|
|
<script nonce="[[.Nonce]]">
|
|
// Check to see if browser is not supported by Grafana
|
|
// Source file in app/core/utils/browser.ts & tests make edits there and copy compiled typescript here
|
|
function checkBrowserCompatibility() {
|
|
var isIE = navigator.userAgent.indexOf('MSIE') > -1;
|
|
var isEdge = navigator.userAgent.indexOf('Edge/') > -1 || navigator.userAgent.indexOf('Edg/') > -1;
|
|
var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
|
var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
|
|
|
|
/* Check for
|
|
<= IE11 (Trident 7)
|
|
Edge <= 16
|
|
Firefox <= 64
|
|
Chrome <= 54
|
|
*/
|
|
var isEdgeVersion = /Edge\/([0-9.]+)/.exec(navigator.userAgent);
|
|
|
|
if (isIE && parseFloat(/Trident\/([0-9.]+)/.exec(navigator.userAgent)[1]) <= 7) {
|
|
return false;
|
|
} else if (
|
|
isEdge &&
|
|
((isEdgeVersion && parseFloat(isEdgeVersion[1]) <= 16) ||
|
|
parseFloat(/Edg\/([0-9.]+)/.exec(navigator.userAgent)[1]) <= 16)
|
|
) {
|
|
return false;
|
|
} else if (isFirefox && parseFloat(/Firefox\/([0-9.]+)/.exec(navigator.userAgent)[1]) <= 64) {
|
|
return false;
|
|
} else if (isChrome && parseFloat(/Chrome\/([0-9.]+)/.exec(navigator.userAgent)[1]) <= 54) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
if (!checkBrowserCompatibility()) {
|
|
alert('Your browser is not fully supported, please try newer version.');
|
|
}
|
|
</script>
|
|
</div>
|
|
|
|
<div id="reactRoot"></div>
|
|
|
|
<script nonce="[[.Nonce]]">
|
|
window.grafanaBootData = {
|
|
user: [[.User]],
|
|
settings: [[.Settings]],
|
|
navTree: [[.NavTree]],
|
|
themePaths: {
|
|
light: '[[.ContentDeliveryURL]]public/build/<%= htmlWebpackPlugin.files.cssChunks.light %>',
|
|
dark: '[[.ContentDeliveryURL]]public/build/<%= htmlWebpackPlugin.files.cssChunks.dark %>'
|
|
}
|
|
};
|
|
|
|
// Set theme to match system only on startup.
|
|
// Do not react to changes in system theme after startup.
|
|
if (window.grafanaBootData.user.theme === "system") {
|
|
document.body.classList.remove("theme-system");
|
|
var darkQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
var cssLink = document.createElement("link");
|
|
cssLink.rel = 'stylesheet';
|
|
|
|
if (darkQuery.matches) {
|
|
document.body.classList.add("theme-dark");
|
|
cssLink.href = window.grafanaBootData.themePaths.dark;
|
|
window.grafanaBootData.user.lightTheme = false;
|
|
} else {
|
|
document.body.classList.add("theme-light");
|
|
cssLink.href = window.grafanaBootData.themePaths.light;
|
|
window.grafanaBootData.user.lightTheme = true;
|
|
}
|
|
document.head.appendChild(cssLink);
|
|
}
|
|
|
|
window.__grafana_load_failed = function() {
|
|
var preloader = document.getElementsByClassName("preloader");
|
|
if (preloader.length) {
|
|
preloader[0].className = "preloader preloader--done";
|
|
}
|
|
}
|
|
|
|
// In case the js files fails to load the code below will show an info message.
|
|
window.onload = function() {
|
|
if (window.__grafana_app_bundle_loaded) {
|
|
return;
|
|
}
|
|
window.__grafana_load_failed();
|
|
};
|
|
|
|
[[if .ContentDeliveryURL]]
|
|
window.public_cdn_path = '[[.ContentDeliveryURL]]public/build/';
|
|
[[end]]
|
|
[[if .Nonce]]
|
|
window.nonce = '[[.Nonce]]';
|
|
[[end]]
|
|
</script>
|
|
|
|
[[if .GoogleTagManagerId]]
|
|
<!-- Google Tag Manager -->
|
|
<script nonce="[[.Nonce]]">
|
|
dataLayer = [
|
|
{
|
|
IsSignedIn: '[[.User.IsSignedIn]]',
|
|
Email: '[[.User.Email]]',
|
|
Name: '[[.User.Name]]',
|
|
UserId: '[[.User.Id]]',
|
|
OrgId: '[[.User.OrgId]]',
|
|
OrgName: '[[.User.OrgName]]',
|
|
},
|
|
];
|
|
</script>
|
|
<noscript>
|
|
<iframe
|
|
src="//www.googletagmanager.com/ns.html?id=[[.GoogleTagManagerId]]"
|
|
height="0"
|
|
width="0"
|
|
style="display: none; visibility: hidden"
|
|
></iframe>
|
|
</noscript>
|
|
<script nonce="[[.Nonce]]">
|
|
(function (w, d, s, l, i) {
|
|
w[l] = w[l] || [];
|
|
w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
|
|
var f = d.getElementsByTagName(s)[0],
|
|
j = d.createElement(s),
|
|
dl = l != 'dataLayer' ? '&l=' + l : '';
|
|
j.async = true;
|
|
j.src = '//www.googletagmanager.com/gtm.js?id=' + i + dl;
|
|
f.parentNode.insertBefore(j, f);
|
|
})(window, document, 'script', 'dataLayer', '[[.GoogleTagManagerId]]');
|
|
</script>
|
|
<!-- End Google Tag Manager -->
|
|
[[end]] <% for (index in htmlWebpackPlugin.files.js) { %> <% if (htmlWebpackPlugin.files.jsIntegrity) { %>
|
|
<script
|
|
nonce="[[.Nonce]]"
|
|
src="[[.ContentDeliveryURL]]<%= htmlWebpackPlugin.files.js[index] %>"
|
|
type="text/javascript"
|
|
integrity="<%= htmlWebpackPlugin.files.jsIntegrity[index] %>"
|
|
crossorigin="<%= webpackConfig.output.crossOriginLoading %>"
|
|
></script>
|
|
<% } else { %>
|
|
<script
|
|
nonce="[[.Nonce]]"
|
|
src="[[.ContentDeliveryURL]]<%= htmlWebpackPlugin.files.js[index] %>"
|
|
type="text/javascript"
|
|
></script>
|
|
<% } %> <% } %>
|
|
|
|
<script nonce="[[.Nonce]]">
|
|
performance.mark('frontend_boot_js_done_time_seconds');
|
|
</script>
|
|
</body>
|
|
</html>
|