Skip to content

Commit

Permalink
feat: Add ability to set default theme for UI (#2062)
Browse files Browse the repository at this point in the history
* feat: Add ability to set default theme for UI

* fix(schema): Added new configuration value to schema config

* Update config/flipt.schema.cue

Co-authored-by: George <[email protected]>

* Update config/flipt.schema.json

Co-authored-by: George <[email protected]>

---------

Co-authored-by: George <[email protected]>
  • Loading branch information
Jamess-Lucass and GeorgeMac authored Aug 31, 2023
1 parent 402a8a0 commit c082585
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 16 deletions.
1 change: 1 addition & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

# ui:
# enabled: true
# default_theme: system

# cors:
# enabled: false
Expand Down
5 changes: 4 additions & 1 deletion config/flipt.schema.cue
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,10 @@ import "strings"
}
}

#ui: enabled?: bool | *true
#ui: {
enabled?: bool | *true
default_theme?: "light" | "dark" | *"system"
}

#audit: {
sinks?: {
Expand Down
15 changes: 9 additions & 6 deletions config/flipt.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down Expand Up @@ -436,10 +436,7 @@
"type": "integer"
},
"conn_max_lifetime": {
"oneOf": [
{"type": "integer"},
{"type": "string"}
]
"oneOf": [{ "type": "integer" }, { "type": "string" }]
},
"prepared_statements_enabled": {
"type": "boolean"
Expand Down Expand Up @@ -637,6 +634,12 @@
"type": "boolean",
"default": true,
"deprecated": true
},
"default_theme": {
"type": "string",
"enum": ["light", "dark", "system"],
"default": "system",
"deprecated": false
}
},
"title": "UI"
Expand Down
1 change: 1 addition & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
3 changes: 2 additions & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,8 @@ func DefaultConfig() *Config {
},

UI: UIConfig{
Enabled: true,
Enabled: true,
DefaultTheme: SystemUITheme,
},

Cors: CorsConfig{
Expand Down
14 changes: 12 additions & 2 deletions internal/config/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions ui/src/app/meta/metaSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -23,6 +24,9 @@ const initialState: IMetaSlice = {
storage: {
type: StorageType.DATABASE,
readOnly: false
},
ui: {
defaultTheme: Theme.SYSTEM
}
}
};
Expand Down
4 changes: 1 addition & 3 deletions ui/src/app/preferences/Preferences.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -45,15 +44,14 @@ export default function Preferences() {
<Select
id="location"
name="location"
value={theme || Theme.LIGHT}
value={theme || Theme.SYSTEM}
options={[
{ value: Theme.LIGHT, label: 'Light' },
{ value: Theme.DARK, label: 'Dark' },
{ value: Theme.SYSTEM, label: 'System' }
]}
onChange={(e) => {
dispatch(themeChanged(e.target.value as Theme));
nightwind.enable(Theme.DARK === (e.target.value as Theme));
}}
/>
</div>
Expand Down
17 changes: 16 additions & 1 deletion ui/src/app/preferences/preferencesSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
import { createSlice } from '@reduxjs/toolkit';
import { RootState } from '~/store';

Check warning on line 3 in ui/src/app/preferences/preferencesSlice.ts

View workflow job for this annotation

GitHub Actions / Lint UI

Insert `fetchConfigAsync·}·from·'~/app/meta/metaSlice';⏎import·{·`
import { Theme, Timezone } from '~/types/Preferences';

Check warning on line 4 in ui/src/app/preferences/preferencesSlice.ts

View workflow job for this annotation

GitHub Actions / Lint UI

Delete `';⏎import·{·fetchConfigAsync·}·from·'~/app/meta/metaSlice`
import { fetchConfigAsync } from '~/app/meta/metaSlice';

export const preferencesKey = 'preferences';

interface IPreferencesState {
theme: Theme;
timezone: Timezone;
}

const initialState: IPreferencesState = {
theme: Theme.LIGHT,
theme: Theme.SYSTEM,
timezone: Timezone.LOCAL
};

Expand All @@ -23,6 +26,18 @@ export const preferencesSlice = createSlice({
timezoneChanged: (state, action) => {
state.timezone = action.payload;
}
},
extraReducers(builder) {
builder.addCase(fetchConfigAsync.fulfilled, (state, action) => {
const currentPreference = JSON.parse(
localStorage.getItem(preferencesKey) || '{}'
) as IPreferencesState;

// If there isn't currently a set theme, set to the default theme
if (!currentPreference.theme) {
state.theme = action.payload.ui.defaultTheme;
}
});
}
});

Expand Down
6 changes: 4 additions & 2 deletions ui/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import {

import { metaSlice } from './app/meta/metaSlice';
import { namespacesSlice } from './app/namespaces/namespacesSlice';
import { preferencesSlice } from './app/preferences/preferencesSlice';
import {
preferencesKey,
preferencesSlice
} from './app/preferences/preferencesSlice';
import { LoadingStatus } from './types/Meta';

const listenerMiddleware = createListenerMiddleware();

const preferencesKey = 'preferences';
const namespaceKey = 'namespace';

listenerMiddleware.startListening({
Expand Down
7 changes: 7 additions & 0 deletions ui/src/types/Meta.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Theme } from './Preferences';

export interface IInfo {
version: string;
latestVersion?: string;
Expand All @@ -14,8 +16,13 @@ export interface IStorage {
readOnly?: boolean;
}

export interface IUI {
defaultTheme: Theme;
}

export interface IConfig {
storage: IStorage;
ui: IUI;
}

export enum StorageType {
Expand Down

0 comments on commit c082585

Please sign in to comment.