diff --git a/client/src/App.tsx b/client/src/App.tsx index d58f4ad..7210f3d 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -18,10 +18,6 @@ if (localStorage.theme) { store.dispatch(setTheme(localStorage.theme)); } -if (localStorage.customTitle) { - document.title = localStorage.customTitle; -} - const App = (): JSX.Element => { return ( diff --git a/client/src/components/Apps/AppForm/AppForm.tsx b/client/src/components/Apps/AppForm/AppForm.tsx index cffeb19..e9c7beb 100644 --- a/client/src/components/Apps/AppForm/AppForm.tsx +++ b/client/src/components/Apps/AppForm/AppForm.tsx @@ -100,10 +100,10 @@ const AppForm = (props: ComponentProps): JSX.Element => { /> + > {' '}Check supported URL formats diff --git a/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx b/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx index 9341565..eb83013 100644 --- a/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx +++ b/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx @@ -186,10 +186,10 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { /> + > {' '}Check supported URL formats diff --git a/client/src/components/Home/Home.tsx b/client/src/components/Home/Home.tsx index ab41ac2..854c04f 100644 --- a/client/src/components/Home/Home.tsx +++ b/client/src/components/Home/Home.tsx @@ -27,6 +27,9 @@ import WeatherWidget from '../Widgets/WeatherWidget/WeatherWidget'; import { greeter } from './functions/greeter'; import { dateTime } from './functions/dateTime'; +// Utils +import { searchConfig } from '../../utility'; + interface ComponentProps { getApps: Function; getCategories: Function; @@ -67,26 +70,36 @@ const Home = (props: ComponentProps): JSX.Element => { // Refresh greeter and time useEffect(() => { - const interval = setInterval(() => { - setHeader({ - dateTime: dateTime(), - greeting: greeter() - }) - }, 1000); + let interval: any; + + // Start interval only when hideHeader is false + if (searchConfig('hideHeader', 0) !== 1) { + interval = setInterval(() => { + setHeader({ + dateTime: dateTime(), + greeting: greeter() + }) + }, 1000); + } return () => clearInterval(interval); }, []) - + return ( -
-

{header.dateTime}

- Go to Settings - -

{header.greeting}

- -
-
+ {searchConfig('hideHeader', 0) !== 1 + ? ( +
+

{header.dateTime}

+ Go to Settings + +

{header.greeting}

+ +
+
+ ) + :
+ } {appsLoading diff --git a/client/src/components/Settings/OtherSettings/OtherSettings.tsx b/client/src/components/Settings/OtherSettings/OtherSettings.tsx index 7a6090e..5df8be7 100644 --- a/client/src/components/Settings/OtherSettings/OtherSettings.tsx +++ b/client/src/components/Settings/OtherSettings/OtherSettings.tsx @@ -1,69 +1,56 @@ import { useState, useEffect, ChangeEvent, FormEvent } from 'react'; -import axios from 'axios'; -import { connect } from 'react-redux'; +// Redux +import { connect } from 'react-redux'; +import { createNotification, updateConfig } from '../../../store/actions'; + +// Typescript +import { GlobalState, NewNotification, SettingsForm } from '../../../interfaces'; + +// UI import InputGroup from '../../UI/Forms/InputGroup/InputGroup'; import Button from '../../UI/Buttons/Button/Button'; -import { createNotification } from '../../../store/actions'; -import { ApiResponse, Config, NewNotification } from '../../../interfaces'; -interface FormState { - customTitle: string; - pinAppsByDefault: number; - pinCategoriesByDefault: number; -} +// Utils +import { searchConfig } from '../../../utility'; interface ComponentProps { createNotification: (notification: NewNotification) => void; + updateConfig: (formData: SettingsForm) => void; + loading: boolean; } const OtherSettings = (props: ComponentProps): JSX.Element => { - const [formData, setFormData] = useState({ + // Initial state + const [formData, setFormData] = useState({ customTitle: document.title, - pinAppsByDefault: 0, - pinCategoriesByDefault: 0 + pinAppsByDefault: 1, + pinCategoriesByDefault: 1, + hideHeader: 0 }) - // get initial config + // Get config useEffect(() => { - axios.get>('/api/config?keys=customTitle,pinAppsByDefault,pinCategoriesByDefault') - .then(data => { - let tmpFormData = { ...formData }; + setFormData({ + customTitle: searchConfig('customTitle', 'Flame'), + pinAppsByDefault: searchConfig('pinAppsByDefault', 1), + pinCategoriesByDefault: searchConfig('pinCategoriesByDefault', 1), + hideHeader: searchConfig('hideHeader', 0) + }) + }, [props.loading]); - data.data.data.forEach((config: Config) => { - let value: string | number = config.value; - if (config.valueType === 'number') { - value = parseFloat(value); - } - - tmpFormData = { - ...tmpFormData, - [config.key]: value - } - }) - - setFormData(tmpFormData); - }) - .catch(err => console.log(err)); - }, []) - - const formSubmitHandler = (e: FormEvent) => { + // Form handler + const formSubmitHandler = async (e: FormEvent) => { e.preventDefault(); - axios.put>('/api/config', formData) - .then(() => { - props.createNotification({ - title: 'Success', - message: 'Settings updated' - }) - }) - .catch((err) => console.log(err)); + // Save settings + await props.updateConfig(formData); // update local page title - localStorage.setItem('customTitle', formData.customTitle); document.title = formData.customTitle; } + // Input handler const inputChangeHandler = (e: ChangeEvent, isNumber?: boolean) => { let value: string | number = e.target.value; @@ -80,7 +67,7 @@ const OtherSettings = (props: ComponentProps): JSX.Element => { return (
formSubmitHandler(e)}> - + { + + + +
) } -export default connect(null, { createNotification })(OtherSettings); \ No newline at end of file +const mapStateToProps = (state: GlobalState) => { + return { + loading: state.config.loading + } +} + +export default connect(mapStateToProps, { createNotification, updateConfig })(OtherSettings); \ No newline at end of file diff --git a/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx b/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx index 6f14cfc..912aced 100644 --- a/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx +++ b/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx @@ -22,6 +22,7 @@ interface ComponentProps { } const WeatherSettings = (props: ComponentProps): JSX.Element => { + // Initial state const [formData, setFormData] = useState({ WEATHER_API_KEY: '', lat: 0, @@ -29,19 +30,7 @@ const WeatherSettings = (props: ComponentProps): JSX.Element => { isCelsius: 1 }) - const inputChangeHandler = (e: ChangeEvent, isNumber?: boolean) => { - let value: string | number = e.target.value; - - if (isNumber) { - value = parseFloat(value); - } - - setFormData({ - ...formData, - [e.target.name]: value - }) - } - + // Get config useEffect(() => { setFormData({ WEATHER_API_KEY: searchConfig('WEATHER_API_KEY', ''), @@ -51,6 +40,7 @@ const WeatherSettings = (props: ComponentProps): JSX.Element => { }) }, [props.loading]); + // Form handler const formSubmitHandler = async (e: FormEvent) => { e.preventDefault(); @@ -58,7 +48,7 @@ const WeatherSettings = (props: ComponentProps): JSX.Element => { if ((formData.lat || formData.long) && !formData.WEATHER_API_KEY) { props.createNotification({ title: 'Warning', - message: 'API Key is missing. Weather Module will NOT work' + message: 'API key is missing. Weather Module will NOT work' }) } @@ -81,10 +71,24 @@ const WeatherSettings = (props: ComponentProps): JSX.Element => { }); } + // Input handler + const inputChangeHandler = (e: ChangeEvent, isNumber?: boolean) => { + let value: string | number = e.target.value; + + if (isNumber) { + value = parseFloat(value); + } + + setFormData({ + ...formData, + [e.target.name]: value + }) + } + return (
formSubmitHandler(e)}> - + { - + { - + { /> - +