diff --git a/config/default.yml b/config/default.yml index 885ff0952c..56389f0667 100644 --- a/config/default.yml +++ b/config/default.yml @@ -9,6 +9,7 @@ # ui: # enabled: true +# default_theme: system # cors: # enabled: false diff --git a/config/flipt.schema.cue b/config/flipt.schema.cue index e26d116e47..14996e2613 100644 --- a/config/flipt.schema.cue +++ b/config/flipt.schema.cue @@ -216,7 +216,10 @@ import "strings" } } - #ui: enabled?: bool | *true + #ui: { + enabled?: bool | *true + default_theme?: "light" | "dark" | *"system" + } #audit: { sinks?: { diff --git a/config/flipt.schema.json b/config/flipt.schema.json index 5728a29fb1..1e0fb3679f 100644 --- a/config/flipt.schema.json +++ b/config/flipt.schema.json @@ -66,8 +66,8 @@ "properties": { "domain": { "type": "string" }, "secure": { "type": "boolean" }, - "token_lifetime": {"type": "string"}, - "state_lifetime": {"type": "string"}, + "token_lifetime": { "type": "string" }, + "state_lifetime": { "type": "string" }, "csrf": { "type": "object", "properties": { @@ -436,10 +436,7 @@ "type": "integer" }, "conn_max_lifetime": { - "oneOf": [ - {"type": "integer"}, - {"type": "string"} - ] + "oneOf": [{ "type": "integer" }, { "type": "string" }] }, "prepared_statements_enabled": { "type": "boolean" @@ -637,6 +634,12 @@ "type": "boolean", "default": true, "deprecated": true + }, + "default_theme": { + "type": "string", + "enum": ["light", "dark", "system"], + "default": "system", + "deprecated": false } }, "title": "UI" diff --git a/go.work.sum b/go.work.sum index 88978686a2..a6a3ae777a 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1115,6 +1115,7 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= diff --git a/internal/config/config.go b/internal/config/config.go index 4563569fb7..8fee65f62c 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -434,7 +434,8 @@ func DefaultConfig() *Config { }, UI: UIConfig{ - Enabled: true, + Enabled: true, + DefaultTheme: SystemUITheme, }, Cors: CorsConfig{ diff --git a/internal/config/ui.go b/internal/config/ui.go index cdf1ba9305..76a26f4687 100644 --- a/internal/config/ui.go +++ b/internal/config/ui.go @@ -2,18 +2,28 @@ package config import "github.com/spf13/viper" +type UITheme string + +const ( + SystemUITheme = UITheme("system") + DarkUITheme = UITheme("dark") + LightUITheme = UITheme("light") +) + // cheers up the unparam linter var _ defaulter = (*UIConfig)(nil) // UIConfig contains fields, which control the behaviour // of Flipt's user interface. type UIConfig struct { - Enabled bool `json:"enabled" mapstructure:"enabled"` + Enabled bool `json:"enabled" mapstructure:"enabled"` + DefaultTheme UITheme `json:"defaultTheme" mapstructure:"default_theme"` } func (c *UIConfig) setDefaults(v *viper.Viper) error { v.SetDefault("ui", map[string]any{ - "enabled": true, + "enabled": true, + "default_theme": SystemUITheme, }) return nil diff --git a/ui/src/app/meta/metaSlice.ts b/ui/src/app/meta/metaSlice.ts index 9a7afa4692..8adcee3685 100644 --- a/ui/src/app/meta/metaSlice.ts +++ b/ui/src/app/meta/metaSlice.ts @@ -2,6 +2,7 @@ import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; import { getConfig, getInfo } from '~/data/api'; import { IConfig, IInfo, StorageType } from '~/types/Meta'; +import { Theme } from '~/types/Preferences'; interface IMetaSlice { info: IInfo; @@ -23,6 +24,9 @@ const initialState: IMetaSlice = { storage: { type: StorageType.DATABASE, readOnly: false + }, + ui: { + defaultTheme: Theme.SYSTEM } } }; diff --git a/ui/src/app/preferences/Preferences.tsx b/ui/src/app/preferences/Preferences.tsx index 7530b3da7d..d563bbcd61 100644 --- a/ui/src/app/preferences/Preferences.tsx +++ b/ui/src/app/preferences/Preferences.tsx @@ -1,6 +1,5 @@ import { Switch } from '@headlessui/react'; import { Formik } from 'formik'; -import nightwind from 'nightwind/helper'; import { useDispatch, useSelector } from 'react-redux'; import Select from '~/components/forms/Select'; import { Theme, Timezone } from '~/types/Preferences'; @@ -45,7 +44,7 @@ export default function Preferences() {