diff --git a/docs/sources/developers/kinds/core/preferences/schema-reference.md b/docs/sources/developers/kinds/core/preferences/schema-reference.md
new file mode 100644
index 00000000000..fc5bf9ec796
--- /dev/null
+++ b/docs/sources/developers/kinds/core/preferences/schema-reference.md
@@ -0,0 +1,33 @@
+---
+keywords:
+ - grafana
+ - schema
+title: Preferences kind
+---
+> Both documentation generation and kinds schemas are in active development and subject to change without prior notice.
+
+# Preferences kind
+
+## Maturity: merged
+## Version: 0.0
+
+## Properties
+
+| Property | Type | Required | Description |
+|--------------------|---------------------------------------------------|----------|---------------------------------------------------------------------------------|
+| `homeDashboardUID` | string | No | UID for the home dashboard |
+| `language` | string | No | Selected language (beta) |
+| `queryHistory` | [QueryHistoryPreference](#queryhistorypreference) | No | |
+| `theme` | string | No | light, dark, empty is default |
+| `timezone` | string | No | The timezone selection
TODO: this should use the timezone defined in common |
+| `weekStart` | string | No | day of the week (sunday, monday, etc) |
+
+## QueryHistoryPreference
+
+### Properties
+
+| Property | Type | Required | Description |
+|-----------|--------|----------|---------------------------------------------|
+| `homeTab` | string | No | one of: '' | 'query' | 'starred'; |
+
+
diff --git a/kinds/preferences/preferences_kind.cue b/kinds/preferences/preferences_kind.cue
new file mode 100644
index 00000000000..1e4be8b9b82
--- /dev/null
+++ b/kinds/preferences/preferences_kind.cue
@@ -0,0 +1,36 @@
+package kind
+
+name: "Preferences"
+maturity: "merged"
+
+lineage: seqs: [
+ {
+ schemas: [
+ {
+ // UID for the home dashboard
+ homeDashboardUID?: string
+
+ // The timezone selection
+ // TODO: this should use the timezone defined in common
+ timezone?: string
+
+ // day of the week (sunday, monday, etc)
+ weekStart?: string
+
+ // light, dark, empty is default
+ theme?: string
+
+ // Selected language (beta)
+ language?: string
+
+ // Explore query history preferences
+ queryHistory?: #QueryHistoryPreference
+
+ #QueryHistoryPreference: {
+ // one of: '' | 'query' | 'starred';
+ homeTab?: string
+ } @cuetsy(kind="interface") //0.0
+ },
+ ]
+ },
+]
diff --git a/packages/grafana-schema/src/index.gen.ts b/packages/grafana-schema/src/index.gen.ts
index 6e9378c10c7..500568d6555 100644
--- a/packages/grafana-schema/src/index.gen.ts
+++ b/packages/grafana-schema/src/index.gen.ts
@@ -95,6 +95,12 @@ export type {
// Raw generated enums and default consts from playlist kind.
export { defaultPlaylist } from './raw/playlist/x/playlist_types.gen';
+// Raw generated types from Preferences kind.
+export type {
+ Preferences,
+ QueryHistoryPreference
+} from './raw/preferences/x/preferences_types.gen';
+
// Raw generated types from Serviceaccount kind.
export type {
Serviceaccount,
diff --git a/packages/grafana-schema/src/raw/preferences/x/preferences_types.gen.ts b/packages/grafana-schema/src/raw/preferences/x/preferences_types.gen.ts
new file mode 100644
index 00000000000..e18a9375d62
--- /dev/null
+++ b/packages/grafana-schema/src/raw/preferences/x/preferences_types.gen.ts
@@ -0,0 +1,44 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+//
+// Generated by:
+// kinds/gen.go
+// Using jennies:
+// TSTypesJenny
+// LatestMajorsOrXJenny
+//
+// Run 'make gen-cue' from repository root to regenerate.
+
+export interface QueryHistoryPreference {
+ /**
+ * one of: '' | 'query' | 'starred';
+ */
+ homeTab?: string;
+}
+
+export interface Preferences {
+ /**
+ * UID for the home dashboard
+ */
+ homeDashboardUID?: string;
+ /**
+ * Selected language (beta)
+ */
+ language?: string;
+ /**
+ * Explore query history preferences
+ */
+ queryHistory?: QueryHistoryPreference;
+ /**
+ * light, dark, empty is default
+ */
+ theme?: string;
+ /**
+ * The timezone selection
+ * TODO: this should use the timezone defined in common
+ */
+ timezone?: string;
+ /**
+ * day of the week (sunday, monday, etc)
+ */
+ weekStart?: string;
+}
diff --git a/pkg/api/dtos/prefs.go b/pkg/api/dtos/prefs.go
index 4dc3d7cc97c..b92ae22f221 100644
--- a/pkg/api/dtos/prefs.go
+++ b/pkg/api/dtos/prefs.go
@@ -4,17 +4,6 @@ import (
pref "github.com/grafana/grafana/pkg/services/preference"
)
-type Prefs struct {
- Theme string `json:"theme"`
- HomeDashboardID int64 `json:"homeDashboardId"`
- HomeDashboardUID string `json:"homeDashboardUID,omitempty"`
- Timezone string `json:"timezone"`
- WeekStart string `json:"weekStart"`
- Language string `json:"language"`
- Navbar pref.NavbarPreference `json:"navbar,omitempty"`
- QueryHistory pref.QueryHistoryPreference `json:"queryHistory,omitempty"`
-}
-
// swagger:model
type UpdatePrefsCmd struct {
// Enum: light,dark
@@ -26,7 +15,6 @@ type UpdatePrefsCmd struct {
// Enum: utc,browser
Timezone string `json:"timezone"`
WeekStart string `json:"weekStart"`
- Navbar *pref.NavbarPreference `json:"navbar,omitempty"`
QueryHistory *pref.QueryHistoryPreference `json:"queryHistory,omitempty"`
Language string `json:"language"`
}
@@ -42,7 +30,6 @@ type PatchPrefsCmd struct {
Timezone *string `json:"timezone,omitempty"`
WeekStart *string `json:"weekStart,omitempty"`
Language *string `json:"language,omitempty"`
- Navbar *pref.NavbarPreference `json:"navbar,omitempty"`
QueryHistory *pref.QueryHistoryPreference `json:"queryHistory,omitempty"`
HomeDashboardUID *string `json:"homeDashboardUID,omitempty"`
}
diff --git a/pkg/api/preferences.go b/pkg/api/preferences.go
index 7f9761723d5..456b5a31dc6 100644
--- a/pkg/api/preferences.go
+++ b/pkg/api/preferences.go
@@ -6,6 +6,7 @@ import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
+ "github.com/grafana/grafana/pkg/kinds/preferences"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/dashboards"
pref "github.com/grafana/grafana/pkg/services/preference"
@@ -83,23 +84,31 @@ func (hs *HTTPServer) getPreferencesFor(ctx context.Context, orgID, userID, team
}
}
- weekStart := ""
- if preference.WeekStart != nil {
- weekStart = *preference.WeekStart
- }
+ dto := preferences.Preferences{}
- dto := dtos.Prefs{
- Theme: preference.Theme,
- HomeDashboardID: preference.HomeDashboardID,
- HomeDashboardUID: dashboardUID,
- Timezone: preference.Timezone,
- WeekStart: weekStart,
+ if preference.WeekStart != nil && *preference.WeekStart != "" {
+ dto.WeekStart = preference.WeekStart
+ }
+ if preference.Theme != "" {
+ dto.Theme = &preference.Theme
+ }
+ if dashboardUID != "" {
+ dto.HomeDashboardUID = &dashboardUID
+ }
+ if preference.Timezone != "" {
+ dto.Timezone = &preference.Timezone
}
if preference.JSONData != nil {
- dto.Language = preference.JSONData.Language
- dto.Navbar = preference.JSONData.Navbar
- dto.QueryHistory = preference.JSONData.QueryHistory
+ if preference.JSONData.Language != "" {
+ dto.Language = &preference.JSONData.Language
+ }
+
+ if preference.JSONData.QueryHistory.HomeTab != "" {
+ dto.QueryHistory = &preferences.QueryHistoryPreference{
+ HomeTab: &preference.JSONData.QueryHistory.HomeTab,
+ }
+ }
}
return response.JSON(http.StatusOK, &dto)
@@ -155,7 +164,6 @@ func (hs *HTTPServer) updatePreferencesFor(ctx context.Context, orgID, userID, t
WeekStart: dtoCmd.WeekStart,
HomeDashboardID: dtoCmd.HomeDashboardID,
QueryHistory: dtoCmd.QueryHistory,
- Navbar: dtoCmd.Navbar,
}
if err := hs.preferenceService.Save(ctx, &saveCmd); err != nil {
@@ -214,7 +222,6 @@ func (hs *HTTPServer) patchPreferencesFor(ctx context.Context, orgID, userID, te
WeekStart: dtoCmd.WeekStart,
HomeDashboardID: dtoCmd.HomeDashboardID,
Language: dtoCmd.Language,
- Navbar: dtoCmd.Navbar,
QueryHistory: dtoCmd.QueryHistory,
}
@@ -292,7 +299,7 @@ type UpdateOrgPreferencesParams struct {
// swagger:response getPreferencesResponse
type GetPreferencesResponse struct {
// in:body
- Body dtos.Prefs `json:"body"`
+ Body preferences.Preferences `json:"body"`
}
// swagger:parameters patchUserPreferences
diff --git a/pkg/kinds/preferences/preferences_kind_gen.go b/pkg/kinds/preferences/preferences_kind_gen.go
new file mode 100644
index 00000000000..4ffd0a15688
--- /dev/null
+++ b/pkg/kinds/preferences/preferences_kind_gen.go
@@ -0,0 +1,113 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+//
+// Generated by:
+// kinds/gen.go
+// Using jennies:
+// CoreKindJenny
+//
+// Run 'make gen-cue' from repository root to regenerate.
+
+package preferences
+
+import (
+ "github.com/grafana/grafana/pkg/kindsys"
+ "github.com/grafana/thema"
+ "github.com/grafana/thema/vmux"
+)
+
+// rootrel is the relative path from the grafana repository root to the
+// directory containing the .cue files in which this kind is declared. Necessary
+// for runtime errors related to the declaration and/or lineage to provide
+// a real path to the correct .cue file.
+const rootrel string = "kinds/preferences"
+
+// TODO standard generated docs
+type Kind struct {
+ lin thema.ConvergentLineage[*Preferences]
+ jcodec vmux.Codec
+ valmux vmux.ValueMux[*Preferences]
+ decl kindsys.Decl[kindsys.CoreProperties]
+}
+
+// type guard
+var _ kindsys.Core = &Kind{}
+
+// TODO standard generated docs
+func NewKind(rt *thema.Runtime, opts ...thema.BindOption) (*Kind, error) {
+ decl, err := kindsys.LoadCoreKind(rootrel, rt.Context(), nil)
+ if err != nil {
+ return nil, err
+ }
+ k := &Kind{
+ decl: decl,
+ }
+
+ lin, err := decl.Some().BindKindLineage(rt, opts...)
+ if err != nil {
+ return nil, err
+ }
+
+ // Get the thema.Schema that the meta says is in the current version (which
+ // codegen ensures is always the latest)
+ cursch := thema.SchemaP(lin, k.decl.Properties.CurrentVersion)
+ tsch, err := thema.BindType[*Preferences](cursch, &Preferences{})
+ if err != nil {
+ // Should be unreachable, modulo bugs in the Thema->Go code generator
+ return nil, err
+ }
+
+ k.jcodec = vmux.NewJSONCodec("preferences.json")
+ k.lin = tsch.ConvergentLineage()
+ k.valmux = vmux.NewValueMux(k.lin.TypedSchema(), k.jcodec)
+ return k, nil
+}
+
+// TODO standard generated docs
+func (k *Kind) Name() string {
+ return "preferences"
+}
+
+// TODO standard generated docs
+func (k *Kind) MachineName() string {
+ return "preferences"
+}
+
+// TODO standard generated docs
+func (k *Kind) Lineage() thema.Lineage {
+ return k.lin
+}
+
+// TODO standard generated docs
+func (k *Kind) ConvergentLineage() thema.ConvergentLineage[*Preferences] {
+ return k.lin
+}
+
+// JSONValueMux is a version multiplexer that maps a []byte containing JSON data
+// at any schematized dashboard version to an instance of Preferences.
+//
+// Validation and translation errors emitted from this func will identify the
+// input bytes as "dashboard.json".
+//
+// This is a thin wrapper around Thema's [vmux.ValueMux].
+func (k *Kind) JSONValueMux(b []byte) (*Preferences, thema.TranslationLacunas, error) {
+ return k.valmux(b)
+}
+
+// TODO standard generated docs
+func (k *Kind) Maturity() kindsys.Maturity {
+ return k.decl.Properties.Maturity
+}
+
+// Decl returns the [kindsys.Decl] containing both CUE and Go representations of the
+// preferences declaration in .cue files.
+func (k *Kind) Decl() kindsys.Decl[kindsys.CoreProperties] {
+ return k.decl
+}
+
+// Props returns a [kindsys.SomeKindProps], with underlying type [kindsys.CoreProperties],
+// representing the static properties declared in the preferences kind.
+//
+// This method is identical to calling Decl().Props. It is provided to satisfy [kindsys.Interface].
+func (k *Kind) Props() kindsys.SomeKindProperties {
+ return k.decl.Properties
+}
diff --git a/pkg/kinds/preferences/preferences_types_gen.go b/pkg/kinds/preferences/preferences_types_gen.go
new file mode 100644
index 00000000000..9ab65c6c388
--- /dev/null
+++ b/pkg/kinds/preferences/preferences_types_gen.go
@@ -0,0 +1,37 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+//
+// Generated by:
+// kinds/gen.go
+// Using jennies:
+// GoTypesJenny
+// LatestJenny
+//
+// Run 'make gen-cue' from repository root to regenerate.
+
+package preferences
+
+// QueryHistoryPreference defines model for QueryHistoryPreference.
+type QueryHistoryPreference struct {
+ // one of: '' | 'query' | 'starred';
+ HomeTab *string `json:"homeTab,omitempty"`
+}
+
+// Preferences defines model for preferences.
+type Preferences struct {
+ // UID for the home dashboard
+ HomeDashboardUID *string `json:"homeDashboardUID,omitempty"`
+
+ // Selected language (beta)
+ Language *string `json:"language,omitempty"`
+ QueryHistory *QueryHistoryPreference `json:"queryHistory,omitempty"`
+
+ // light, dark, empty is default
+ Theme *string `json:"theme,omitempty"`
+
+ // The timezone selection
+ // TODO: this should use the timezone defined in common
+ Timezone *string `json:"timezone,omitempty"`
+
+ // day of the week (sunday, monday, etc)
+ WeekStart *string `json:"weekStart,omitempty"`
+}
diff --git a/pkg/kindsys/report.json b/pkg/kindsys/report.json
index 35d314c27c9..2f97bb2c5dd 100644
--- a/pkg/kindsys/report.json
+++ b/pkg/kindsys/report.json
@@ -1211,6 +1211,32 @@
"pluralName": "PostgreSQLDataSourceCfgs",
"schemaInterface": "DataSourceCfg"
},
+ "preferences": {
+ "category": "core",
+ "codeowners": [
+ "grafana/grafana-as-code",
+ "grafana/grafana-bi-squad",
+ "grafana/plugins-platform-frontend",
+ "grafana/user-essentials"
+ ],
+ "currentVersion": [
+ 0,
+ 0
+ ],
+ "grafanaMaturityCount": 0,
+ "lineageIsGroup": false,
+ "links": {
+ "docs": "https://grafana.com/docs/grafana/next/developers/kinds/core/preferences/schema-reference",
+ "go": "https://github.com/grafana/grafana/tree/main/pkg/kinds/preferences",
+ "schema": "https://github.com/grafana/grafana/tree/main/kinds/preferences/preferences_kind.cue",
+ "ts": "https://github.com/grafana/grafana/tree/main/packages/grafana-schema/src/raw/preferences/x/preferences_types.gen.ts"
+ },
+ "machineName": "preferences",
+ "maturity": "merged",
+ "name": "Preferences",
+ "pluralMachineName": "preferencess",
+ "pluralName": "Preferencess"
+ },
"prometheusdataquery": {
"category": "composable",
"codeowners": [],
@@ -1739,6 +1765,7 @@
"datasource",
"folder",
"playlist",
+ "preferences",
"query",
"queryhistory",
"serviceaccount",
@@ -1746,7 +1773,7 @@
"thumb",
"user"
],
- "count": 11
+ "count": 12
}
},
"maturity": {
@@ -1777,10 +1804,11 @@
"items": [
"alertgroupspanelcfg",
"playlist",
+ "preferences",
"serviceaccount",
"team"
],
- "count": 4
+ "count": 5
},
"planned": {
"name": "planned",
diff --git a/pkg/registry/corekind/base_gen.go b/pkg/registry/corekind/base_gen.go
index f3e52a08564..3770ae0250e 100644
--- a/pkg/registry/corekind/base_gen.go
+++ b/pkg/registry/corekind/base_gen.go
@@ -14,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/kinds/dashboard"
"github.com/grafana/grafana/pkg/kinds/playlist"
+ "github.com/grafana/grafana/pkg/kinds/preferences"
"github.com/grafana/grafana/pkg/kinds/serviceaccount"
"github.com/grafana/grafana/pkg/kinds/team"
"github.com/grafana/grafana/pkg/kindsys"
@@ -34,6 +35,7 @@ type Base struct {
all []kindsys.Core
dashboard *dashboard.Kind
playlist *playlist.Kind
+ preferences *preferences.Kind
serviceaccount *serviceaccount.Kind
team *team.Kind
}
@@ -42,6 +44,7 @@ type Base struct {
var (
_ kindsys.Core = &dashboard.Kind{}
_ kindsys.Core = &playlist.Kind{}
+ _ kindsys.Core = &preferences.Kind{}
_ kindsys.Core = &serviceaccount.Kind{}
_ kindsys.Core = &team.Kind{}
)
@@ -56,6 +59,11 @@ func (b *Base) Playlist() *playlist.Kind {
return b.playlist
}
+// Preferences returns the [kindsys.Interface] implementation for the preferences kind.
+func (b *Base) Preferences() *preferences.Kind {
+ return b.preferences
+}
+
// Serviceaccount returns the [kindsys.Interface] implementation for the serviceaccount kind.
func (b *Base) Serviceaccount() *serviceaccount.Kind {
return b.serviceaccount
@@ -82,6 +90,12 @@ func doNewBase(rt *thema.Runtime) *Base {
}
reg.all = append(reg.all, reg.playlist)
+ reg.preferences, err = preferences.NewKind(rt)
+ if err != nil {
+ panic(fmt.Sprintf("error while initializing the preferences Kind: %s", err))
+ }
+ reg.all = append(reg.all, reg.preferences)
+
reg.serviceaccount, err = serviceaccount.NewKind(rt)
if err != nil {
panic(fmt.Sprintf("error while initializing the serviceaccount Kind: %s", err))
diff --git a/pkg/services/preference/model.go b/pkg/services/preference/model.go
index 9bb6a2ef22f..7505255a3bd 100644
--- a/pkg/services/preference/model.go
+++ b/pkg/services/preference/model.go
@@ -50,7 +50,6 @@ type SavePreferenceCommand struct {
WeekStart string `json:"weekStart,omitempty"`
Theme string `json:"theme,omitempty"`
Language string `json:"language,omitempty"`
- Navbar *NavbarPreference `json:"navbar,omitempty"`
QueryHistory *QueryHistoryPreference `json:"queryHistory,omitempty"`
}
@@ -65,24 +64,11 @@ type PatchPreferenceCommand struct {
WeekStart *string `json:"weekStart,omitempty"`
Theme *string `json:"theme,omitempty"`
Language *string `json:"language,omitempty"`
- Navbar *NavbarPreference `json:"navbar,omitempty"`
QueryHistory *QueryHistoryPreference `json:"queryHistory,omitempty"`
}
-type NavLink struct {
- ID string `json:"id,omitempty"`
- Text string `json:"text,omitempty"`
- Url string `json:"url,omitempty"`
- Target string `json:"target,omitempty"`
-}
-
-type NavbarPreference struct {
- SavedItems []NavLink `json:"savedItems"`
-}
-
type PreferenceJSONData struct {
Language string `json:"language"`
- Navbar NavbarPreference `json:"navbar"`
QueryHistory QueryHistoryPreference `json:"queryHistory"`
}
diff --git a/pkg/services/preference/prefimpl/pref.go b/pkg/services/preference/prefimpl/pref.go
index feadcbfa06e..1ddc5b94cf0 100644
--- a/pkg/services/preference/prefimpl/pref.go
+++ b/pkg/services/preference/prefimpl/pref.go
@@ -65,10 +65,6 @@ func (s *Service) GetWithDefaults(ctx context.Context, query *pref.GetPreference
res.JSONData.Language = p.JSONData.Language
}
- if len(p.JSONData.Navbar.SavedItems) > 0 {
- res.JSONData.Navbar = p.JSONData.Navbar
- }
-
if p.JSONData.QueryHistory.HomeTab != "" {
res.JSONData.QueryHistory.HomeTab = p.JSONData.QueryHistory.HomeTab
}
@@ -134,9 +130,6 @@ func (s *Service) Save(ctx context.Context, cmd *pref.SavePreferenceCommand) err
Language: cmd.Language,
}
- if cmd.Navbar != nil {
- preference.JSONData.Navbar = *cmd.Navbar
- }
if cmd.QueryHistory != nil {
preference.JSONData.QueryHistory = *cmd.QueryHistory
}
@@ -173,15 +166,6 @@ func (s *Service) Patch(ctx context.Context, cmd *pref.PatchPreferenceCommand) e
preference.JSONData.Language = *cmd.Language
}
- if cmd.Navbar != nil {
- if preference.JSONData == nil {
- preference.JSONData = &pref.PreferenceJSONData{}
- }
- if cmd.Navbar.SavedItems != nil {
- preference.JSONData.Navbar.SavedItems = cmd.Navbar.SavedItems
- }
- }
-
if cmd.QueryHistory != nil {
if preference.JSONData == nil {
preference.JSONData = &pref.PreferenceJSONData{}
@@ -210,16 +194,6 @@ func (s *Service) Patch(ctx context.Context, cmd *pref.PatchPreferenceCommand) e
preference.Updated = time.Now()
preference.Version += 1
- // Wrap this in an if statement to maintain backwards compatibility
- if cmd.Navbar != nil {
- if preference.JSONData == nil {
- preference.JSONData = &pref.PreferenceJSONData{}
- }
- if cmd.Navbar.SavedItems != nil {
- preference.JSONData.Navbar.SavedItems = cmd.Navbar.SavedItems
- }
- }
-
if exists {
err = s.store.Update(ctx, preference)
} else {
diff --git a/pkg/services/preference/prefimpl/pref_test.go b/pkg/services/preference/prefimpl/pref_test.go
index 0f5868b0117..9463901ce7f 100644
--- a/pkg/services/preference/prefimpl/pref_test.go
+++ b/pkg/services/preference/prefimpl/pref_test.go
@@ -174,51 +174,15 @@ func TestGetDefaults_JSONData(t *testing.T) {
queryPreference := pref.QueryHistoryPreference{
HomeTab: "hometab",
}
- userNavbarPreferences := pref.NavbarPreference{
- SavedItems: []pref.NavLink{{
- ID: "explore",
- Text: "Explore",
- Url: "/explore",
- }},
- }
- orgNavbarPreferences := pref.NavbarPreference{
- SavedItems: []pref.NavLink{{
- ID: "alerting",
- Text: "Alerting",
- Url: "/alerting",
- }},
- }
- team1NavbarPreferences := pref.NavbarPreference{
- SavedItems: []pref.NavLink{{
- ID: "dashboards",
- Text: "Dashboards",
- Url: "/dashboards",
- }},
- }
- team2NavbarPreferences := pref.NavbarPreference{
- SavedItems: []pref.NavLink{{
- ID: "home",
- Text: "Home",
- Url: "/home",
- }},
- }
userPreferencesJsonData := pref.PreferenceJSONData{
- Navbar: userNavbarPreferences,
QueryHistory: queryPreference,
}
- orgPreferencesJsonData := pref.PreferenceJSONData{
- Navbar: orgNavbarPreferences,
- }
+ orgPreferencesJsonData := pref.PreferenceJSONData{}
orgPreferencesWithLanguageJsonData := pref.PreferenceJSONData{
- Navbar: orgNavbarPreferences,
Language: "en-GB",
}
- team2PreferencesJsonData := pref.PreferenceJSONData{
- Navbar: team2NavbarPreferences,
- }
- team1PreferencesJsonData := pref.PreferenceJSONData{
- Navbar: team1NavbarPreferences,
- }
+ team2PreferencesJsonData := pref.PreferenceJSONData{}
+ team1PreferencesJsonData := pref.PreferenceJSONData{}
t.Run("users have precedence over org", func(t *testing.T) {
prefService := &Service{
@@ -274,7 +238,6 @@ func TestGetDefaults_JSONData(t *testing.T) {
WeekStart: &weekStart,
JSONData: &pref.PreferenceJSONData{
Language: "en-GB",
- Navbar: userNavbarPreferences,
QueryHistory: queryPreference,
},
}, preference)
diff --git a/pkg/services/preference/prefimpl/store_test.go b/pkg/services/preference/prefimpl/store_test.go
index 0773c1c7134..43d56d4c97f 100644
--- a/pkg/services/preference/prefimpl/store_test.go
+++ b/pkg/services/preference/prefimpl/store_test.go
@@ -20,13 +20,6 @@ func testIntegrationPreferencesDataAccess(t *testing.T, fn getStore) {
weekStartOne := "1"
ss := db.InitTestDB(t)
prefStore := fn(ss)
- orgNavbarPreferences := pref.NavbarPreference{
- SavedItems: []pref.NavLink{{
- ID: "alerting",
- Text: "Alerting",
- Url: "/alerting",
- }},
- }
t.Run("Get with saved org and user home dashboard returns not found", func(t *testing.T) {
query := &pref.Preference{OrgID: 1, UserID: 1, TeamID: 2}
@@ -124,7 +117,7 @@ func testIntegrationPreferencesDataAccess(t *testing.T, fn getStore) {
Timezone: "browser",
HomeDashboardID: 5,
WeekStart: &weekStartOne,
- JSONData: &pref.PreferenceJSONData{Navbar: orgNavbarPreferences},
+ JSONData: &pref.PreferenceJSONData{},
Created: time.Now(),
Updated: time.Now(),
})
diff --git a/pkg/services/store/entity/models.go b/pkg/services/store/entity/models.go
index a4c7388388f..9f5ea100e19 100644
--- a/pkg/services/store/entity/models.go
+++ b/pkg/services/store/entity/models.go
@@ -4,13 +4,16 @@ package entity
// NOTE: the object store is in heavy development, and the locations will likely continue to move
//-----------------------------------------------------------------------------------------------------
-import "context"
+import (
+ "context"
+)
const (
- StandardKindDashboard = "dashboard"
- StandardKindPlaylist = "playlist"
- StandardKindSnapshot = "snapshot"
- StandardKindFolder = "folder"
+ StandardKindDashboard = "dashboard"
+ StandardKindPlaylist = "playlist"
+ StandardKindSnapshot = "snapshot"
+ StandardKindFolder = "folder"
+ StandardKindPreferences = "preferences"
// StandardKindDataSource: not a real kind yet, but used to define references from dashboards
// Types: influx, prometheus, testdata, ...
diff --git a/pkg/services/store/kind/preferences/summary.go b/pkg/services/store/kind/preferences/summary.go
new file mode 100644
index 00000000000..1efdae01633
--- /dev/null
+++ b/pkg/services/store/kind/preferences/summary.go
@@ -0,0 +1,54 @@
+package preferences
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "strings"
+
+ "github.com/grafana/grafana/pkg/kinds/preferences"
+ "github.com/grafana/grafana/pkg/services/store/entity"
+)
+
+func GetEntityKindInfo() entity.EntityKindInfo {
+ return entity.EntityKindInfo{
+ ID: entity.StandardKindPreferences,
+ Name: "Preferences",
+ }
+}
+
+func GetEntitySummaryBuilder() entity.EntitySummaryBuilder {
+ return func(ctx context.Context, uid string, body []byte) (*entity.EntitySummary, []byte, error) {
+ if uid != "default" {
+ parts := strings.Split(uid, "-")
+ if len(parts) != 2 {
+ return nil, nil, fmt.Errorf("expecting UID: default, user-{#}, or team-{#}")
+ }
+ if !(parts[0] == "team" || parts[0] == "user") {
+ return nil, nil, fmt.Errorf("expecting UID: default, user-{#}, or team-{#}")
+ }
+ }
+
+ obj := &preferences.Preferences{}
+ err := json.Unmarshal(body, obj)
+ if err != nil {
+ return nil, nil, err // unable to read object
+ }
+
+ summary := &entity.EntitySummary{
+ Kind: entity.StandardKindPreferences,
+ Name: uid, // team-${id} | user-${id}
+ UID: uid,
+ }
+
+ if obj.HomeDashboardUID != nil && *obj.HomeDashboardUID != "" {
+ summary.References = append(summary.References, &entity.EntityExternalReference{
+ Kind: entity.StandardKindDashboard,
+ UID: *obj.HomeDashboardUID,
+ })
+ }
+
+ out, err := json.MarshalIndent(obj, "", " ")
+ return summary, out, err
+ }
+}
diff --git a/pkg/services/store/kind/registry.go b/pkg/services/store/kind/registry.go
index d977511ea4c..f720c68d452 100644
--- a/pkg/services/store/kind/registry.go
+++ b/pkg/services/store/kind/registry.go
@@ -14,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/services/store/kind/jsonobj"
"github.com/grafana/grafana/pkg/services/store/kind/playlist"
"github.com/grafana/grafana/pkg/services/store/kind/png"
+ "github.com/grafana/grafana/pkg/services/store/kind/preferences"
"github.com/grafana/grafana/pkg/services/store/kind/snapshot"
"github.com/grafana/grafana/pkg/services/store/kind/svg"
"github.com/grafana/grafana/pkg/setting"
@@ -61,6 +62,10 @@ func NewKindRegistry() KindRegistry {
info: jsonobj.GetEntityKindInfo(),
builder: jsonobj.GetEntitySummaryBuilder(),
}
+ kinds[entity.StandardKindPreferences] = &kindValues{
+ info: preferences.GetEntityKindInfo(),
+ builder: preferences.GetEntitySummaryBuilder(),
+ }
// create a registry
reg := ®istry{
diff --git a/pkg/services/store/kind/registry_test.go b/pkg/services/store/kind/registry_test.go
index 419b029e64e..9443edc1263 100644
--- a/pkg/services/store/kind/registry_test.go
+++ b/pkg/services/store/kind/registry_test.go
@@ -26,6 +26,7 @@ func TestKindRegistry(t *testing.T) {
"jsonobj",
"playlist",
"png",
+ "preferences",
"snapshot",
"test",
}, ids)
diff --git a/public/app/core/components/SharedPreferences/SharedPreferences.test.tsx b/public/app/core/components/SharedPreferences/SharedPreferences.test.tsx
index e6b4fc69fcc..a1ea4c4ff0d 100644
--- a/public/app/core/components/SharedPreferences/SharedPreferences.test.tsx
+++ b/public/app/core/components/SharedPreferences/SharedPreferences.test.tsx
@@ -5,7 +5,7 @@ import TestProvider from 'test/helpers/TestProvider';
import { assertInstanceOf } from 'test/helpers/asserts';
import { getSelectParent, selectOptionInTest } from 'test/helpers/selectOptionInTest';
-import { UserPreferencesDTO } from 'app/types';
+import { Preferences as UserPreferencesDTO } from '@grafana/schema/src/raw/preferences/x/preferences_types.gen';
import SharedPreferences from './SharedPreferences';
diff --git a/public/app/core/components/SharedPreferences/SharedPreferences.tsx b/public/app/core/components/SharedPreferences/SharedPreferences.tsx
index 5a6486e250d..73b7ee09290 100644
--- a/public/app/core/components/SharedPreferences/SharedPreferences.tsx
+++ b/public/app/core/components/SharedPreferences/SharedPreferences.tsx
@@ -4,6 +4,7 @@ import React, { PureComponent } from 'react';
import { FeatureState, SelectableValue } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { config, reportInteraction } from '@grafana/runtime';
+import { Preferences as UserPreferencesDTO } from '@grafana/schema/src/raw/preferences/x/preferences_types.gen';
import {
Button,
Field,
@@ -21,7 +22,6 @@ import { DashboardPicker } from 'app/core/components/Select/DashboardPicker';
import { t, Trans } from 'app/core/internationalization';
import { LANGUAGES } from 'app/core/internationalization/constants';
import { PreferencesService } from 'app/core/services/PreferencesService';
-import { UserPreferencesDTO } from 'app/types';
export interface Props {
resourceUri: string;
@@ -130,6 +130,10 @@ export class SharedPreferences extends PureComponent {
const { disabled } = this.props;
const styles = getStyles();
const languages = getLanguageOptions();
+ let currentThemeOption = this.themeOptions[0].value;
+ if (theme?.length) {
+ currentThemeOption = this.themeOptions.find((item) => item.value === theme)?.value;
+ }
return (