mirror of
https://github.com/pawelmalak/flame.git
synced 2026-03-09 14:03:11 +08:00
Moved Themer to Settings. Added option to set default theme
This commit is contained in:
@@ -59,7 +59,7 @@ export const DockerSettings = (): JSX.Element => {
|
||||
<SettingsHeadline text="Docker" />
|
||||
{/* CUSTOM DOCKER SOCKET HOST */}
|
||||
<InputGroup>
|
||||
<label htmlFor="dockerHost">Docker Host</label>
|
||||
<label htmlFor="dockerHost">Docker host</label>
|
||||
<input
|
||||
type="text"
|
||||
id="dockerHost"
|
||||
|
||||
@@ -70,7 +70,7 @@ export const SearchSettings = (): JSX.Element => {
|
||||
>
|
||||
<SettingsHeadline text="General" />
|
||||
<InputGroup>
|
||||
<label htmlFor="defaultSearchProvider">Default Search Provider</label>
|
||||
<label htmlFor="defaultSearchProvider">Default search provider</label>
|
||||
<select
|
||||
id="defaultSearchProvider"
|
||||
name="defaultSearchProvider"
|
||||
|
||||
@@ -11,7 +11,7 @@ import { Route as SettingsRoute } from '../../interfaces';
|
||||
import classes from './Settings.module.css';
|
||||
|
||||
// Components
|
||||
import { Themer } from '../Themer/Themer';
|
||||
import { Themer } from './Themer/Themer';
|
||||
import { WeatherSettings } from './WeatherSettings/WeatherSettings';
|
||||
import { UISettings } from './UISettings/UISettings';
|
||||
import { AppDetails } from './AppDetails/AppDetails';
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
.ThemePreview {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.ThemePreview:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ThemePreview p {
|
||||
text-transform: capitalize;
|
||||
margin: 8px 0;
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.ColorsPreview {
|
||||
display: flex;
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
.ColorPreview {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
@media (min-width: 340px) {
|
||||
.ColorPreview {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
32
client/src/components/Settings/Themer/ThemePreview.tsx
Normal file
32
client/src/components/Settings/Themer/ThemePreview.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Theme } from '../../../interfaces/Theme';
|
||||
import classes from './ThemePreview.module.css';
|
||||
|
||||
interface Props {
|
||||
theme: Theme;
|
||||
applyTheme: Function;
|
||||
}
|
||||
|
||||
export const ThemePreview = (props: Props): JSX.Element => {
|
||||
return (
|
||||
<div
|
||||
className={classes.ThemePreview}
|
||||
onClick={() => props.applyTheme(props.theme.name)}
|
||||
>
|
||||
<div className={classes.ColorsPreview}>
|
||||
<div
|
||||
className={classes.ColorPreview}
|
||||
style={{ backgroundColor: props.theme.colors.background }}
|
||||
></div>
|
||||
<div
|
||||
className={classes.ColorPreview}
|
||||
style={{ backgroundColor: props.theme.colors.primary }}
|
||||
></div>
|
||||
<div
|
||||
className={classes.ColorPreview}
|
||||
style={{ backgroundColor: props.theme.colors.accent }}
|
||||
></div>
|
||||
</div>
|
||||
<p>{props.theme.name}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
18
client/src/components/Settings/Themer/Themer.module.css
Normal file
18
client/src/components/Settings/Themer/Themer.module.css
Normal file
@@ -0,0 +1,18 @@
|
||||
.ThemerGrid {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-auto-rows: 100px;
|
||||
}
|
||||
|
||||
@media (min-width: 340px) {
|
||||
.ThemerGrid {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 680px) {
|
||||
.ThemerGrid {
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
}
|
||||
}
|
||||
101
client/src/components/Settings/Themer/Themer.tsx
Normal file
101
client/src/components/Settings/Themer/Themer.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import { ChangeEvent, FormEvent, Fragment, useEffect, useState } from 'react';
|
||||
|
||||
// Redux
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { actionCreators } from '../../../store';
|
||||
|
||||
// Typescript
|
||||
import { Theme, ThemeSettingsForm } from '../../../interfaces';
|
||||
|
||||
// Components
|
||||
import { ThemePreview } from './ThemePreview';
|
||||
import { Button, InputGroup, SettingsHeadline } from '../../UI';
|
||||
|
||||
// Other
|
||||
import classes from './Themer.module.css';
|
||||
import { themes } from './themes.json';
|
||||
import { State } from '../../../store/reducers';
|
||||
import { inputHandler, themeSettingsTemplate } from '../../../utility';
|
||||
|
||||
export const Themer = (): JSX.Element => {
|
||||
const {
|
||||
auth: { isAuthenticated },
|
||||
config: { loading, config },
|
||||
} = useSelector((state: State) => state);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const { setTheme, updateConfig } = bindActionCreators(
|
||||
actionCreators,
|
||||
dispatch
|
||||
);
|
||||
|
||||
// Initial state
|
||||
const [formData, setFormData] = useState<ThemeSettingsForm>(
|
||||
themeSettingsTemplate
|
||||
);
|
||||
|
||||
// Get config
|
||||
useEffect(() => {
|
||||
setFormData({
|
||||
...config,
|
||||
});
|
||||
}, [loading]);
|
||||
|
||||
// Form handler
|
||||
const formSubmitHandler = async (e: FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
// Save settings
|
||||
await updateConfig(formData);
|
||||
};
|
||||
|
||||
// Input handler
|
||||
const inputChangeHandler = (
|
||||
e: ChangeEvent<HTMLInputElement | HTMLSelectElement>,
|
||||
options?: { isNumber?: boolean; isBool?: boolean }
|
||||
) => {
|
||||
inputHandler<ThemeSettingsForm>({
|
||||
e,
|
||||
options,
|
||||
setStateHandler: setFormData,
|
||||
state: formData,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SettingsHeadline text="Set theme" />
|
||||
<div className={classes.ThemerGrid}>
|
||||
{themes.map(
|
||||
(theme: Theme, idx: number): JSX.Element => (
|
||||
<ThemePreview key={idx} theme={theme} applyTheme={setTheme} />
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
|
||||
{isAuthenticated && (
|
||||
<form onSubmit={formSubmitHandler}>
|
||||
<SettingsHeadline text="Other settings" />
|
||||
<InputGroup>
|
||||
<label htmlFor="defaultTheme">Default theme (for new users)</label>
|
||||
<select
|
||||
id="defaultTheme"
|
||||
name="defaultTheme"
|
||||
value={formData.defaultTheme}
|
||||
onChange={(e) => inputChangeHandler(e)}
|
||||
>
|
||||
{themes.map((theme: Theme, idx) => (
|
||||
<option key={idx} value={theme.name}>
|
||||
{theme.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</InputGroup>
|
||||
|
||||
<Button>Save changes</Button>
|
||||
</form>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
124
client/src/components/Settings/Themer/themes.json
Normal file
124
client/src/components/Settings/Themer/themes.json
Normal file
@@ -0,0 +1,124 @@
|
||||
{
|
||||
"themes": [
|
||||
{
|
||||
"name": "blackboard",
|
||||
"colors": {
|
||||
"background": "#1a1a1a",
|
||||
"primary": "#FFFDEA",
|
||||
"accent": "#5c5c5c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "gazette",
|
||||
"colors": {
|
||||
"background": "#F2F7FF",
|
||||
"primary": "#000000",
|
||||
"accent": "#5c5c5c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "espresso",
|
||||
"colors": {
|
||||
"background": "#21211F",
|
||||
"primary": "#D1B59A",
|
||||
"accent": "#4E4E4E"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cab",
|
||||
"colors": {
|
||||
"background": "#F6D305",
|
||||
"primary": "#1F1F1F",
|
||||
"accent": "#424242"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cloud",
|
||||
"colors": {
|
||||
"background": "#f1f2f0",
|
||||
"primary": "#35342f",
|
||||
"accent": "#37bbe4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lime",
|
||||
"colors": {
|
||||
"background": "#263238",
|
||||
"primary": "#AABBC3",
|
||||
"accent": "#aeea00"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "white",
|
||||
"colors": {
|
||||
"background": "#ffffff",
|
||||
"primary": "#222222",
|
||||
"accent": "#dddddd"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tron",
|
||||
"colors": {
|
||||
"background": "#242B33",
|
||||
"primary": "#EFFBFF",
|
||||
"accent": "#6EE2FF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "blues",
|
||||
"colors": {
|
||||
"background": "#2B2C56",
|
||||
"primary": "#EFF1FC",
|
||||
"accent": "#6677EB"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "passion",
|
||||
"colors": {
|
||||
"background": "#f5f5f5",
|
||||
"primary": "#12005e",
|
||||
"accent": "#8e24aa"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "chalk",
|
||||
"colors": {
|
||||
"background": "#263238",
|
||||
"primary": "#AABBC3",
|
||||
"accent": "#FF869A"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "paper",
|
||||
"colors": {
|
||||
"background": "#F8F6F1",
|
||||
"primary": "#4C432E",
|
||||
"accent": "#AA9A73"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "neon",
|
||||
"colors": {
|
||||
"background": "#091833",
|
||||
"primary": "#EFFBFF",
|
||||
"accent": "#ea00d9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "pumpkin",
|
||||
"colors": {
|
||||
"background": "#2d3436",
|
||||
"primary": "#EFFBFF",
|
||||
"accent": "#ffa500"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "onedark",
|
||||
"colors": {
|
||||
"background": "#282c34",
|
||||
"primary": "#dfd9d6",
|
||||
"accent": "#98c379"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user