diff --git a/client/src/components/Settings/Themer/ThemeBuilder/ThemeCreator.tsx b/client/src/components/Settings/Themer/ThemeBuilder/ThemeCreator.tsx
index 84e1896..f271aa9 100644
--- a/client/src/components/Settings/Themer/ThemeBuilder/ThemeCreator.tsx
+++ b/client/src/components/Settings/Themer/ThemeBuilder/ThemeCreator.tsx
@@ -1,26 +1,24 @@
-import { ChangeEvent, FormEvent, useState, useEffect } from 'react';
-
-// Redux
+import { ChangeEvent, FormEvent, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { bindActionCreators } from 'redux';
+
+import { Theme } from '../../../../interfaces';
import { actionCreators } from '../../../../store';
import { State } from '../../../../store/reducers';
-
-// UI
import { Button, InputGroup, ModalForm } from '../../../UI';
import classes from './ThemeCreator.module.css';
+// Redux
+// UI
// Other
-import { Theme } from '../../../../interfaces';
-
interface Props {
modalHandler: () => void;
}
export const ThemeCreator = ({ modalHandler }: Props): JSX.Element => {
const {
- theme: { activeTheme, themeInEdit },
- } = useSelector((state: State) => state);
+ activeTheme, themeInEdit
+ } = useSelector((state: State) => state.theme);
const { addTheme, updateTheme, editTheme } = bindActionCreators(
actionCreators,
@@ -39,7 +37,7 @@ export const ThemeCreator = ({ modalHandler }: Props): JSX.Element => {
useEffect(() => {
setFormData({ ...formData, colors: activeTheme.colors });
- }, [activeTheme]);
+ }, [activeTheme.colors]);
useEffect(() => {
if (themeInEdit) {
diff --git a/client/src/components/Settings/Themer/ThemeBuilder/ThemeEditor.tsx b/client/src/components/Settings/Themer/ThemeBuilder/ThemeEditor.tsx
index 888e576..3cfa1c0 100644
--- a/client/src/components/Settings/Themer/ThemeBuilder/ThemeEditor.tsx
+++ b/client/src/components/Settings/Themer/ThemeBuilder/ThemeEditor.tsx
@@ -1,23 +1,20 @@
import { Fragment } from 'react';
-
-// Redux
-import { useSelector, useDispatch } from 'react-redux';
+import { useDispatch, useSelector } from 'react-redux';
import { bindActionCreators } from 'redux';
+
import { Theme } from '../../../../interfaces';
import { actionCreators } from '../../../../store';
import { State } from '../../../../store/reducers';
-
-// Other
import { ActionIcons, CompactTable, Icon, ModalForm } from '../../../UI';
+// Redux
+// Other
interface Props {
modalHandler: () => void;
}
export const ThemeEditor = (props: Props): JSX.Element => {
- const {
- theme: { userThemes },
- } = useSelector((state: State) => state);
+ const userThemes = useSelector((state: State) => state.theme.userThemes);
const { deleteTheme, editTheme } = bindActionCreators(
actionCreators,
diff --git a/client/src/components/Settings/Themer/Themer.tsx b/client/src/components/Settings/Themer/Themer.tsx
index ae2ac7d..b3aed83 100644
--- a/client/src/components/Settings/Themer/Themer.tsx
+++ b/client/src/components/Settings/Themer/Themer.tsx
@@ -1,32 +1,25 @@
import { ChangeEvent, FormEvent, Fragment, useEffect, useState } from 'react';
-
-// Redux
import { useDispatch, useSelector } from 'react-redux';
import { bindActionCreators } from 'redux';
+
+import { Theme, ThemeSettingsForm } from '../../../interfaces';
import { actionCreators } from '../../../store';
import { State } from '../../../store/reducers';
-
-// Typescript
-import { Theme, ThemeSettingsForm } from '../../../interfaces';
-
-// Components
+import { inputHandler, parseThemeToPAB, themeSettingsTemplate } from '../../../utility';
import { Button, InputGroup, SettingsHeadline, Spinner } from '../../UI';
import { ThemeBuilder } from './ThemeBuilder/ThemeBuilder';
import { ThemeGrid } from './ThemeGrid/ThemeGrid';
+// Redux
+// Typescript
+// Components
// Other
-import {
- inputHandler,
- parseThemeToPAB,
- themeSettingsTemplate,
-} from '../../../utility';
-
-export const Themer = (): JSX.Element => {
- const {
- auth: { isAuthenticated },
- config: { loading, config },
- theme: { themes, userThemes },
- } = useSelector((state: State) => state);
+export const Themer = (): JSX.Element => {
+ const themes = useSelector((state: State) => state.theme.themes);
+ const userThemes = useSelector((state: State) => state.theme.userThemes);
+ const config = useSelector((state: State) => state.config.config);
+ const loading = useSelector((state: State) => state.config.loading);
+ const isAuthenticated = useSelector((state: State) => state.auth.isAuthenticated);
const dispatch = useDispatch();
const { updateConfig } = bindActionCreators(actionCreators, dispatch);
diff --git a/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx b/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx
index a6819d8..3b7f7c1 100644
--- a/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx
+++ b/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx
@@ -1,21 +1,18 @@
-import { useState, ChangeEvent, useEffect, FormEvent } from 'react';
import axios from 'axios';
-
-// Redux
+import { ChangeEvent, FormEvent, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { bindActionCreators } from 'redux';
+
+import { ApiResponse, Weather, WeatherForm } from '../../../interfaces';
import { actionCreators } from '../../../store';
import { State } from '../../../store/reducers';
-
-// Typescript
-import { ApiResponse, Weather, WeatherForm } from '../../../interfaces';
-
-// UI
-import { InputGroup, Button, SettingsHeadline } from '../../UI';
-
-// Utils
import { inputHandler, weatherSettingsTemplate } from '../../../utility';
+import { Button, InputGroup, SettingsHeadline } from '../../UI';
+// Redux
+// Typescript
+// UI
+// Utils
export const WeatherSettings = (): JSX.Element => {
const { loading, config } = useSelector((state: State) => state.config);
diff --git a/client/src/components/Widgets/WeatherWidget/WeatherWidget.tsx b/client/src/components/Widgets/WeatherWidget/WeatherWidget.tsx
index d300328..5933c82 100644
--- a/client/src/components/Widgets/WeatherWidget/WeatherWidget.tsx
+++ b/client/src/components/Widgets/WeatherWidget/WeatherWidget.tsx
@@ -1,20 +1,17 @@
-import { useState, useEffect, Fragment } from 'react';
import axios from 'axios';
-
-// Redux
+import { Fragment, useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
-// Typescript
-import { Weather, ApiResponse } from '../../../interfaces';
-
-// CSS
-import classes from './WeatherWidget.module.css';
-
-// UI
-import { WeatherIcon } from '../../UI';
+import { ApiResponse, Weather } from '../../../interfaces';
import { State } from '../../../store/reducers';
import { weatherTemplate } from '../../../utility/templateObjects/weatherTemplate';
+import { WeatherIcon } from '../../UI';
+import classes from './WeatherWidget.module.css';
+// Redux
+// Typescript
+// CSS
+// UI
export const WeatherWidget = (): JSX.Element => {
const { loading: configLoading, config } = useSelector(
(state: State) => state.config
diff --git a/client/src/index.tsx b/client/src/index.tsx
index d4da2cf..2d6006c 100644
--- a/client/src/index.tsx
+++ b/client/src/index.tsx
@@ -1,17 +1,17 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
import './index.css';
+import React from 'react';
+import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
-import { store } from './store/store';
import { App } from './App';
+import { store } from './store/store';
-ReactDOM.render(
+const container = document.getElementById('root');
+const root = createRoot(container!); // createRoot(container!) if you use TypeScript
+root.render(
- ,
- document.getElementById('root')
-);
+ );
\ No newline at end of file
diff --git a/client/src/store/action-creators/auth.ts b/client/src/store/action-creators/auth.ts
index cc4112b..12ba112 100644
--- a/client/src/store/action-creators/auth.ts
+++ b/client/src/store/action-creators/auth.ts
@@ -61,7 +61,7 @@ export const autoLogin = () => async (dispatch: Dispatch
) => {
export const authError =
(error: unknown, showNotification: boolean) =>
(dispatch: Dispatch) => {
- const apiError = error as AxiosError;
+ const apiError = error as AxiosError;
if (showNotification) {
dispatch({
diff --git a/client/src/utility/checkVersion.ts b/client/src/utility/checkVersion.ts
index 7a95679..39ccc80 100644
--- a/client/src/utility/checkVersion.ts
+++ b/client/src/utility/checkVersion.ts
@@ -1,6 +1,7 @@
import axios from 'axios';
-import { store } from '../store/store';
+
import { createNotification } from '../store/action-creators';
+import { store } from '../store/store';
export const checkVersion = async (isForced: boolean = false) => {
try {
diff --git a/client/src/utility/escapeRegex.ts b/client/src/utility/escapeRegex.ts
index 3fc002a..9cb7be2 100644
--- a/client/src/utility/escapeRegex.ts
+++ b/client/src/utility/escapeRegex.ts
@@ -2,5 +2,5 @@
* https://stackoverflow.com/a/30851002/16957052
*/
export const escapeRegex = (exp: string) => {
- return exp.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
+ return exp.replace(/[-[\]{}()*+!<=:?./\\^$|#\s,]/g, '\\$&');
};
diff --git a/client/src/utility/validators.ts b/client/src/utility/validators.ts
index df4de72..c4aa8a1 100644
--- a/client/src/utility/validators.ts
+++ b/client/src/utility/validators.ts
@@ -1,6 +1,6 @@
export const isUrlOrIp = (data: string): boolean => {
const regex =
- /^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?|^((http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/i;
+ /^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([-.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?|^((http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/i;
return regex.test(data);
};