almost working some of the time
This commit is contained in:
@@ -1991,6 +1991,12 @@ default_datasource_uid =
|
||||
;feature1 = true
|
||||
;feature2 = false
|
||||
|
||||
# default for the navigation sidebar docking behavior
|
||||
# true = docked by default
|
||||
# false = undocked by default
|
||||
# When unspecified the current Grafana default remains (true).
|
||||
;default_sidebar_docked = false
|
||||
|
||||
[date_formats]
|
||||
# For information on what formatting patterns that are supported https://momentjs.com/docs/#/displaying/
|
||||
|
||||
|
||||
@@ -220,6 +220,27 @@ func (hs *HTTPServer) setIndexViewData(c *contextmodel.ReqContext) (*dtos.IndexV
|
||||
|
||||
hs.HooksService.RunIndexDataHooks(&data, c)
|
||||
|
||||
if data.Settings.FeatureToggles == nil {
|
||||
data.Settings.FeatureToggles = map[string]bool{}
|
||||
}
|
||||
|
||||
// Use value populated by your loader (pkg/setting/feature_toggles.go). If not wired,
|
||||
// you can temporarily hardcode here for testing or read env.
|
||||
data.Settings.FeatureToggles["default_sidebar_docked"] = setting.FeatureToggleConfig.DefaultSidebarDocked
|
||||
|
||||
// Example temporary hardcode for quick verification:
|
||||
// data.Settings.FeatureToggles["default_sidebar_docked"] = false
|
||||
|
||||
// Instrumentation: log the runtime value so you can see where it's coming from
|
||||
if c != nil {
|
||||
c.Logger.Info("feature toggle value", "default_sidebar_docked", setting.FeatureToggleConfig.DefaultSidebarDocked)
|
||||
} else if hs != nil && hs.log != nil {
|
||||
hs.log.Info("feature toggle value", "default_sidebar_docked", setting.FeatureToggleConfig.DefaultSidebarDocked)
|
||||
} else {
|
||||
// quick-and-dirty fallback (will print to stdout)
|
||||
fmt.Printf("feature toggle default_sidebar_docked=%v\n", setting.FeatureToggleConfig.DefaultSidebarDocked)
|
||||
}
|
||||
|
||||
data.NavTree.Sort()
|
||||
|
||||
return &data, nil
|
||||
|
||||
@@ -1019,6 +1019,10 @@ func (cfg *Cfg) loadConfiguration(args CommandLineArgs) (*ini.File, error) {
|
||||
// apply command line overrides
|
||||
cfg.applyCommandLineProperties(commandLineProps, parsedFile)
|
||||
|
||||
// --- ADD THIS LINE TO LOAD FEATURE TOGGLES FROM THE FINAL PARSED INI ---
|
||||
loadFeatureToggles(parsedFile)
|
||||
//
|
||||
|
||||
// evaluate config values containing environment variables
|
||||
err = expandConfig(parsedFile)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,43 +1,121 @@
|
||||
// This script runs very early (before frontend bundles) so we cannot import @grafana/data here.
|
||||
// Disable the lint rule that forbids direct localStorage usage for this file.
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
|
||||
// Early script to initialize grafana.navigation.docked from server bootdata.
|
||||
// Behavior:
|
||||
// - If the user already has a preference (no companion ".auto" key) we never override it.
|
||||
// - If we set the value automatically, we set a companion key to mark it.
|
||||
// - If later the authoritative bootdata promise resolves, we will override only if
|
||||
// the current value was previously auto-set by us.
|
||||
(function () {
|
||||
try {
|
||||
let key = 'grafana.navigation.docked';
|
||||
let autoKey = key + '.auto';
|
||||
|
||||
// If already set (user choice exists), do nothing.
|
||||
if (localStorage.getItem(key) !== null) {
|
||||
return;
|
||||
function isAutoSet() {
|
||||
try {
|
||||
return localStorage.getItem(autoKey) === '1';
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Try the server-provided boot data (common Grafana pattern)
|
||||
let serverDefault;
|
||||
if (
|
||||
typeof window !== 'undefined' &&
|
||||
window.grafanaBootData &&
|
||||
window.grafanaBootData.settings &&
|
||||
window.grafanaBootData.settings.featureToggles
|
||||
) {
|
||||
serverDefault = window.grafanaBootData.settings.featureToggles.default_sidebar_docked;
|
||||
function setAuto(val) {
|
||||
try {
|
||||
localStorage.setItem(key, val ? 'true' : 'false');
|
||||
localStorage.setItem(autoKey, '1');
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: a page-global var you can set for quick testing in index.html
|
||||
let globalDefault = typeof window !== 'undefined' ? window.__defaultSidebarDocked : undefined;
|
||||
|
||||
// If neither is provided, leave the existing Grafana default (true/docked).
|
||||
let val =
|
||||
typeof serverDefault !== 'undefined'
|
||||
? serverDefault
|
||||
: typeof globalDefault !== 'undefined'
|
||||
? globalDefault
|
||||
: undefined;
|
||||
|
||||
if (typeof val !== 'undefined') {
|
||||
// localStorage stores strings; Grafana historically uses 'true'/'false' for this key.
|
||||
localStorage.setItem(key, val ? 'true' : 'false');
|
||||
function setIfAbsent(val) {
|
||||
try {
|
||||
if (localStorage.getItem(key) === null) {
|
||||
setAuto(val);
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
function setIfAutoOrAbsent(val) {
|
||||
try {
|
||||
let cur = localStorage.getItem(key);
|
||||
if (cur === null || isAutoSet()) {
|
||||
setAuto(val);
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
function applyDefault(preferServer) {
|
||||
try {
|
||||
// If a real user preference exists (not marked as auto) and preferServer is true,
|
||||
// we should NOT override it. setIfAutoOrAbsent will only override if auto or absent.
|
||||
// preferServer indicates this call is from authoritative bootdata (true) or inline (false).
|
||||
let serverDefault;
|
||||
if (
|
||||
typeof window !== 'undefined' &&
|
||||
window.grafanaBootData &&
|
||||
window.grafanaBootData.settings &&
|
||||
window.grafanaBootData.settings.featureToggles &&
|
||||
typeof window.grafanaBootData.settings.featureToggles.default_sidebar_docked !== 'undefined'
|
||||
) {
|
||||
serverDefault = window.grafanaBootData.settings.featureToggles.default_sidebar_docked;
|
||||
}
|
||||
|
||||
let globalDefault = typeof window !== 'undefined' ? window.__defaultSidebarDocked : undefined;
|
||||
|
||||
let val =
|
||||
typeof serverDefault !== 'undefined'
|
||||
? serverDefault
|
||||
: typeof globalDefault !== 'undefined'
|
||||
? globalDefault
|
||||
: undefined;
|
||||
|
||||
if (typeof val === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is called for authoritative data (preferServer === true), allow override of previously
|
||||
// auto-set values; if it's non-authoritative (inline), only set if absent.
|
||||
if (preferServer) {
|
||||
setIfAutoOrAbsent(val);
|
||||
} else {
|
||||
setIfAbsent(val);
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
// Fast-path: try immediate apply from inline bootdata (non-authoritative)
|
||||
applyDefault(false);
|
||||
|
||||
// If async bootdata is fetched, wait for the promise and apply authoritative value
|
||||
try {
|
||||
if (
|
||||
typeof window !== 'undefined' &&
|
||||
window.__grafana_boot_data_promise &&
|
||||
typeof window.__grafana_boot_data_promise.then === 'function'
|
||||
) {
|
||||
window.__grafana_boot_data_promise
|
||||
.then(function () {
|
||||
applyDefault(true);
|
||||
})
|
||||
.catch(function () {
|
||||
// ignore
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
// Fallback: try again shortly after load as a final chance (authoritative)
|
||||
setTimeout(function () {
|
||||
applyDefault(true);
|
||||
}, 1500);
|
||||
} catch (e) {
|
||||
// Keep page stable if something goes wrong
|
||||
// Do not let this break the page
|
||||
}
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user