Added components and logic to dynamically change theme

This commit is contained in:
Alejandro Celaya
2021-02-16 19:25:23 +01:00
committed by Alejandro Celaya
parent f313a39b81
commit 9dbf790cc8
10 changed files with 93 additions and 10 deletions

View File

@@ -2,11 +2,14 @@ import { useEffect, FC } from 'react';
import { Route, Switch } from 'react-router-dom';
import NotFound from './common/NotFound';
import { ServersMap } from './servers/data';
import { Settings } from './settings/reducers/settings';
import { changeThemeInMarkup } from './utils/theme';
import './App.scss';
interface AppProps {
fetchServers: Function;
servers: ServersMap;
settings: Settings;
}
const App = (
@@ -17,12 +20,14 @@ const App = (
EditServer: FC,
Settings: FC,
ShlinkVersionsContainer: FC,
) => ({ fetchServers, servers }: AppProps) => {
// On first load, try to fetch the remote servers if the list is empty
) => ({ fetchServers, servers, settings }: AppProps) => {
useEffect(() => {
// On first load, try to fetch the remote servers if the list is empty
if (Object.keys(servers).length === 0) {
fetchServers();
}
changeThemeInMarkup(settings.ui?.theme ?? 'light');
}, []);
return (

View File

@@ -43,7 +43,7 @@ bottle.serviceFactory(
'Settings',
'ShlinkVersionsContainer',
);
bottle.decorator('App', connect([ 'servers' ], [ 'fetchServers' ]));
bottle.decorator('App', connect([ 'servers', 'settings' ], [ 'fetchServers' ]));
provideCommonServices(bottle, connect, withRouter);
provideApiServices(bottle);

View File

@@ -19,6 +19,9 @@ const RealTimeUpdates = (
<FormGroup>
<ToggleSwitch checked={realTimeUpdates.enabled} onChange={toggleRealTimeUpdates}>
Enable or disable real-time updates, when using Shlink v2.2.0 or newer.
<small className="form-text text-muted">
Real-time updates are currently being <b>{realTimeUpdates.enabled ? 'processed' : 'ignored'}</b>.
</small>
</ToggleSwitch>
</FormGroup>
<FormGroup className="mb-0">

View File

@@ -2,14 +2,19 @@ import { FC } from 'react';
import { Row } from 'reactstrap';
import NoMenuLayout from '../common/NoMenuLayout';
const Settings = (RealTimeUpdates: FC, ShortUrlCreation: FC) => () => (
const Settings = (RealTimeUpdates: FC, ShortUrlCreation: FC, UserInterface:FC) => () => (
<NoMenuLayout>
<Row>
<div className="col-lg-6">
<RealTimeUpdates />
<div className="mb-3 mb-md-4">
<UserInterface />
</div>
<div className="mb-3 mb-md-4">
<ShortUrlCreation />
</div>
</div>
<div className="col-lg-6">
<ShortUrlCreation />
<RealTimeUpdates />
</div>
</Row>
</NoMenuLayout>

View File

@@ -0,0 +1,26 @@
import { FC } from 'react';
import { SimpleCard } from '../utils/SimpleCard';
import ToggleSwitch from '../utils/ToggleSwitch';
import { changeThemeInMarkup, Theme } from '../utils/theme';
import { Settings, UiSettings } from './reducers/settings';
interface UserInterfaceProps {
settings: Settings;
setUiSettings: (settings: UiSettings) => void;
}
export const UserInterface: FC<UserInterfaceProps> = ({ settings: { ui }, setUiSettings }) => (
<SimpleCard title="User interface">
<ToggleSwitch
checked={ui?.theme === 'dark'}
onChange={(useDarkTheme) => {
const theme: Theme = useDarkTheme ? 'dark' : 'light';
setUiSettings({ theme });
changeThemeInMarkup(theme);
}}
>
Use dark theme
</ToggleSwitch>
</SimpleCard>
);

View File

@@ -2,6 +2,7 @@ import { Action } from 'redux';
import { dissoc, mergeDeepRight } from 'ramda';
import { buildReducer } from '../../utils/helpers/redux';
import { RecursivePartial } from '../../utils/utils';
import { Theme } from '../../utils/theme';
export const SET_SETTINGS = 'shlink/realTimeUpdates/SET_SETTINGS';
@@ -19,9 +20,14 @@ export interface ShortUrlCreationSettings {
validateUrls: boolean;
}
export interface UiSettings {
theme: Theme;
}
export interface Settings {
realTimeUpdates: RealTimeUpdatesSettings;
shortUrlCreation?: ShortUrlCreationSettings;
ui?: UiSettings;
}
const initialState: Settings = {
@@ -31,6 +37,9 @@ const initialState: Settings = {
shortUrlCreation: {
validateUrls: false,
},
ui: {
theme: 'light',
},
};
type SettingsAction = Action & Settings;
@@ -55,3 +64,8 @@ export const setShortUrlCreationSettings = (settings: ShortUrlCreationSettings):
type: SET_SETTINGS,
shortUrlCreation: settings,
});
export const setUiSettings = (settings: UiSettings): PartialSettingsAction => ({
type: SET_SETTINGS,
ui: settings,
});

View File

@@ -1,14 +1,20 @@
import Bottle from 'bottlejs';
import RealTimeUpdates from '../RealTimeUpdates';
import Settings from '../Settings';
import { setRealTimeUpdatesInterval, setShortUrlCreationSettings, toggleRealTimeUpdates } from '../reducers/settings';
import {
setRealTimeUpdatesInterval,
setShortUrlCreationSettings,
setUiSettings,
toggleRealTimeUpdates,
} from '../reducers/settings';
import { ConnectDecorator } from '../../container/types';
import { withoutSelectedServer } from '../../servers/helpers/withoutSelectedServer';
import { ShortUrlCreation } from '../ShortUrlCreation';
import { UserInterface } from '../UserInterface';
const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
// Components
bottle.serviceFactory('Settings', Settings, 'RealTimeUpdates', 'ShortUrlCreation');
bottle.serviceFactory('Settings', Settings, 'RealTimeUpdates', 'ShortUrlCreation', 'UserInterface');
bottle.decorator('Settings', withoutSelectedServer);
bottle.decorator('Settings', connect(null, [ 'resetSelectedServer' ]));
@@ -21,10 +27,14 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
bottle.serviceFactory('ShortUrlCreation', () => ShortUrlCreation);
bottle.decorator('ShortUrlCreation', connect([ 'settings' ], [ 'setShortUrlCreationSettings' ]));
bottle.serviceFactory('UserInterface', () => UserInterface);
bottle.decorator('UserInterface', connect([ 'settings' ], [ 'setUiSettings' ]));
// Actions
bottle.serviceFactory('toggleRealTimeUpdates', () => toggleRealTimeUpdates);
bottle.serviceFactory('setRealTimeUpdatesInterval', () => setRealTimeUpdatesInterval);
bottle.serviceFactory('setShortUrlCreationSettings', () => setShortUrlCreationSettings);
bottle.serviceFactory('setUiSettings', () => setUiSettings);
};
export default provideServices;

View File

@@ -5,3 +5,11 @@ export const MAIN_COLOR_ALPHA = 'rgba(70, 150, 229, 0.4)';
export const HIGHLIGHTED_COLOR = '#F77F28';
export const HIGHLIGHTED_COLOR_ALPHA = 'rgba(247, 127, 40, 0.4)';
export type Theme = 'dark' | 'light';
export const changeThemeInMarkup = (theme: Theme) => {
const html = document.getElementsByTagName('html');
html?.[0]?.setAttribute('data-theme', theme);
};