diff --git a/client/src/App.tsx b/client/src/App.tsx index 3968bcd..28c0350 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,38 +1,41 @@ import { BrowserRouter, Route, Switch } from 'react-router-dom'; -import { fetchQueries, getConfig, setTheme } from './store/actions'; +import { actionCreators } from './store'; import 'external-svg-loader'; -// Redux -import { store } from './store/store'; -import { Provider } from 'react-redux'; - // Utils import { checkVersion } from './utility'; // Routes -import Home from './components/Home/Home'; -import Apps from './components/Apps/Apps'; -import Settings from './components/Settings/Settings'; -import Bookmarks from './components/Bookmarks/Bookmarks'; -import NotificationCenter from './components/NotificationCenter/NotificationCenter'; - -// Load config -store.dispatch(getConfig()); - -// Set theme -if (localStorage.theme) { - store.dispatch(setTheme(localStorage.theme)); -} - -// Check for updates -checkVersion(); - -// fetch queries -store.dispatch(fetchQueries()); +import { Home } from './components/Home/Home'; +import { Apps } from './components/Apps/Apps'; +import { Settings } from './components/Settings/Settings'; +import { Bookmarks } from './components/Bookmarks/Bookmarks'; +import { NotificationCenter } from './components/NotificationCenter/NotificationCenter'; +import { useDispatch } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import { useEffect } from 'react'; const App = (): JSX.Element => { + const dispath = useDispatch(); + const { fetchQueries, getConfig, setTheme } = bindActionCreators( + actionCreators, + dispath + ); + + useEffect(() => { + getConfig(); + + if (localStorage.theme) { + setTheme(localStorage.theme); + } + + checkVersion(); + + fetchQueries(); + }, []); + return ( - + <> @@ -42,7 +45,7 @@ const App = (): JSX.Element => { - + ); }; diff --git a/client/src/components/Apps/AppCard/AppCard.tsx b/client/src/components/Apps/AppCard/AppCard.tsx index 803e5dd..dbd17e6 100644 --- a/client/src/components/Apps/AppCard/AppCard.tsx +++ b/client/src/components/Apps/AppCard/AppCard.tsx @@ -1,17 +1,19 @@ import classes from './AppCard.module.css'; -import Icon from '../../UI/Icons/Icon/Icon'; +import { Icon } from '../../UI'; import { iconParser, urlParser } from '../../../utility'; -import { App, Config, GlobalState } from '../../../interfaces'; -import { connect } from 'react-redux'; +import { App } from '../../../interfaces'; +import { useSelector } from 'react-redux'; +import { State } from '../../../store/reducers'; -interface ComponentProps { +interface Props { app: App; pinHandler?: Function; - config: Config; } -const AppCard = (props: ComponentProps): JSX.Element => { +export const AppCard = (props: Props): JSX.Element => { + const { config } = useSelector((state: State) => state.config); + const [displayUrl, redirectUrl] = urlParser(props.app.url); let iconEl: JSX.Element; @@ -42,7 +44,7 @@ const AppCard = (props: ComponentProps): JSX.Element => { return ( @@ -54,11 +56,3 @@ const AppCard = (props: ComponentProps): JSX.Element => { ); }; - -const mapStateToProps = (state: GlobalState) => { - return { - config: state.config.config, - }; -}; - -export default connect(mapStateToProps)(AppCard); diff --git a/client/src/components/Apps/AppForm/AppForm.tsx b/client/src/components/Apps/AppForm/AppForm.tsx index c3ffdad..8c11253 100644 --- a/client/src/components/Apps/AppForm/AppForm.tsx +++ b/client/src/components/Apps/AppForm/AppForm.tsx @@ -1,23 +1,23 @@ import { useState, useEffect, ChangeEvent, SyntheticEvent } from 'react'; -import { connect } from 'react-redux'; -import { addApp, updateApp } from '../../../store/actions'; +import { useDispatch } from 'react-redux'; import { App, NewApp } from '../../../interfaces'; import classes from './AppForm.module.css'; -import ModalForm from '../../UI/Forms/ModalForm/ModalForm'; -import InputGroup from '../../UI/Forms/InputGroup/InputGroup'; -import Button from '../../UI/Buttons/Button/Button'; +import { ModalForm, InputGroup, Button } from '../../UI'; import { inputHandler, newAppTemplate } from '../../../utility'; +import { bindActionCreators } from 'redux'; +import { actionCreators } from '../../../store'; -interface ComponentProps { +interface Props { modalHandler: () => void; - addApp: (formData: NewApp | FormData) => any; - updateApp: (id: number, formData: NewApp | FormData) => any; app?: App; } -const AppForm = (props: ComponentProps): JSX.Element => { +export const AppForm = (props: Props): JSX.Element => { + const dispatch = useDispatch(); + const { addApp, updateApp } = bindActionCreators(actionCreators, dispatch); + const [useCustomIcon, toggleUseCustomIcon] = useState(false); const [customIcon, setCustomIcon] = useState(null); const [formData, setFormData] = useState(newAppTemplate); @@ -68,16 +68,16 @@ const AppForm = (props: ComponentProps): JSX.Element => { if (!props.app) { if (customIcon) { const data = createFormData(); - props.addApp(data); + addApp(data); } else { - props.addApp(formData); + addApp(formData); } } else { if (customIcon) { const data = createFormData(); - props.updateApp(props.app.id, data); + updateApp(props.app.id, data); } else { - props.updateApp(props.app.id, formData); + updateApp(props.app.id, formData); props.modalHandler(); } } @@ -192,5 +192,3 @@ const AppForm = (props: ComponentProps): JSX.Element => { ); }; - -export default connect(null, { addApp, updateApp })(AppForm); diff --git a/client/src/components/Apps/AppGrid/AppGrid.tsx b/client/src/components/Apps/AppGrid/AppGrid.tsx index 30d5c8c..6b02443 100644 --- a/client/src/components/Apps/AppGrid/AppGrid.tsx +++ b/client/src/components/Apps/AppGrid/AppGrid.tsx @@ -2,15 +2,15 @@ import classes from './AppGrid.module.css'; import { Link } from 'react-router-dom'; import { App } from '../../../interfaces/App'; -import AppCard from '../AppCard/AppCard'; +import { AppCard } from '../AppCard/AppCard'; -interface ComponentProps { +interface Props { apps: App[]; totalApps?: number; searching: boolean; } -const AppGrid = (props: ComponentProps): JSX.Element => { +export const AppGrid = (props: Props): JSX.Element => { let apps: JSX.Element; if (props.apps.length > 0) { @@ -49,5 +49,3 @@ const AppGrid = (props: ComponentProps): JSX.Element => { return apps; }; - -export default AppGrid; diff --git a/client/src/components/Apps/AppTable/AppTable.tsx b/client/src/components/Apps/AppTable/AppTable.tsx index 631bd74..ee82144 100644 --- a/client/src/components/Apps/AppTable/AppTable.tsx +++ b/client/src/components/Apps/AppTable/AppTable.tsx @@ -8,48 +8,45 @@ import { import { Link } from 'react-router-dom'; // Redux -import { connect } from 'react-redux'; -import { - pinApp, - deleteApp, - reorderApps, - updateConfig, - createNotification, -} from '../../../store/actions'; +import { useDispatch, useSelector } from 'react-redux'; // Typescript -import { App, Config, GlobalState, NewNotification } from '../../../interfaces'; +import { App } from '../../../interfaces'; // CSS import classes from './AppTable.module.css'; // UI -import Icon from '../../UI/Icons/Icon/Icon'; -import Table from '../../UI/Table/Table'; +import { Icon, Table } from '../../UI'; +import { State } from '../../../store/reducers'; +import { bindActionCreators } from 'redux'; +import { actionCreators } from '../../../store'; -interface ComponentProps { - apps: App[]; - config: Config; - pinApp: (app: App) => void; - deleteApp: (id: number) => void; +interface Props { updateAppHandler: (app: App) => void; - reorderApps: (apps: App[]) => void; - updateConfig: (formData: any) => void; - createNotification: (notification: NewNotification) => void; } -const AppTable = (props: ComponentProps): JSX.Element => { +export const AppTable = (props: Props): JSX.Element => { + const { + apps: { apps }, + config: { config }, + } = useSelector((state: State) => state); + + const dispatch = useDispatch(); + const { pinApp, deleteApp, reorderApps, updateConfig, createNotification } = + bindActionCreators(actionCreators, dispatch); + const [localApps, setLocalApps] = useState([]); const [isCustomOrder, setIsCustomOrder] = useState(false); // Copy apps array useEffect(() => { - setLocalApps([...props.apps]); - }, [props.apps]); + setLocalApps([...apps]); + }, [apps]); // Check ordering useEffect(() => { - const order = props.config.useOrdering; + const order = config.useOrdering; if (order === 'orderId') { setIsCustomOrder(true); @@ -62,7 +59,7 @@ const AppTable = (props: ComponentProps): JSX.Element => { ); if (proceed) { - props.deleteApp(app.id); + deleteApp(app.id); } }; @@ -79,7 +76,7 @@ const AppTable = (props: ComponentProps): JSX.Element => { const dragEndHanlder = (result: DropResult): void => { if (!isCustomOrder) { - props.createNotification({ + createNotification({ title: 'Error', message: 'Custom order is disabled', }); @@ -95,7 +92,7 @@ const AppTable = (props: ComponentProps): JSX.Element => { tmpApps.splice(result.destination.index, 0, movedApp); setLocalApps(tmpApps); - props.reorderApps(tmpApps); + reorderApps(tmpApps); }; return ( @@ -178,9 +175,9 @@ const AppTable = (props: ComponentProps): JSX.Element => {
props.pinApp(app)} + onClick={() => pinApp(app)} onKeyDown={(e) => - keyboardActionHandler(e, app, props.pinApp) + keyboardActionHandler(e, app, pinApp) } tabIndex={0} > @@ -208,20 +205,3 @@ const AppTable = (props: ComponentProps): JSX.Element => { ); }; - -const mapStateToProps = (state: GlobalState) => { - return { - apps: state.app.apps, - config: state.config.config, - }; -}; - -const actions = { - pinApp, - deleteApp, - reorderApps, - updateConfig, - createNotification, -}; - -export default connect(mapStateToProps, actions)(AppTable); diff --git a/client/src/components/Apps/Apps.tsx b/client/src/components/Apps/Apps.tsx index 2c15b35..2185879 100644 --- a/client/src/components/Apps/Apps.tsx +++ b/client/src/components/Apps/Apps.tsx @@ -2,39 +2,37 @@ import { useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; // Redux -import { connect } from 'react-redux'; -import { getApps } from '../../store/actions'; +import { useDispatch, useSelector } from 'react-redux'; // Typescript -import { App, GlobalState } from '../../interfaces'; +import { App } from '../../interfaces'; // CSS import classes from './Apps.module.css'; // UI -import { Container } from '../UI/Layout/Layout'; -import Headline from '../UI/Headlines/Headline/Headline'; -import Spinner from '../UI/Spinner/Spinner'; -import ActionButton from '../UI/Buttons/ActionButton/ActionButton'; -import Modal from '../UI/Modal/Modal'; +import { Headline, Spinner, ActionButton, Modal, Container } from '../UI'; // Subcomponents -import AppGrid from './AppGrid/AppGrid'; -import AppForm from './AppForm/AppForm'; -import AppTable from './AppTable/AppTable'; +import { AppGrid } from './AppGrid/AppGrid'; +import { AppForm } from './AppForm/AppForm'; +import { AppTable } from './AppTable/AppTable'; // Utils import { appTemplate } from '../../utility'; +import { State } from '../../store/reducers'; +import { bindActionCreators } from 'redux'; +import { actionCreators } from '../../store'; -interface ComponentProps { - getApps: Function; - apps: App[]; - loading: boolean; +interface Props { searching: boolean; } -const Apps = (props: ComponentProps): JSX.Element => { - const { getApps, apps, loading, searching = false } = props; +export const Apps = (props: Props): JSX.Element => { + const { apps, loading } = useSelector((state: State) => state.apps); + + const dispatch = useDispatch(); + const { getApps } = bindActionCreators(actionCreators, dispatch); const [modalIsOpen, setModalIsOpen] = useState(false); const [isInEdit, setIsInEdit] = useState(false); @@ -95,12 +93,3 @@ const Apps = (props: ComponentProps): JSX.Element => { ); }; - -const mapStateToProps = (state: GlobalState) => { - return { - apps: state.app.apps, - loading: state.app.loading, - }; -}; - -export default connect(mapStateToProps, { getApps })(Apps); diff --git a/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.tsx b/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.tsx index 93ead02..f3b3bd3 100644 --- a/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.tsx +++ b/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.tsx @@ -1,17 +1,23 @@ -import { Bookmark, Category, Config, GlobalState } from '../../../interfaces'; +import { Fragment } from 'react'; + +import { useSelector } from 'react-redux'; +import { State } from '../../../store/reducers'; + +import { Bookmark, Category } from '../../../interfaces'; + import classes from './BookmarkCard.module.css'; -import Icon from '../../UI/Icons/Icon/Icon'; -import { iconParser, urlParser } from '../../../utility'; -import { Fragment } from 'react'; -import { connect } from 'react-redux'; +import { Icon } from '../../UI'; -interface ComponentProps { +import { iconParser, urlParser } from '../../../utility'; + +interface Props { category: Category; - config: Config; } -const BookmarkCard = (props: ComponentProps): JSX.Element => { +export const BookmarkCard = (props: Props): JSX.Element => { + const { config } = useSelector((state: State) => state.config); + return (

{props.category.name}

@@ -56,7 +62,7 @@ const BookmarkCard = (props: ComponentProps): JSX.Element => { return ( @@ -69,11 +75,3 @@ const BookmarkCard = (props: ComponentProps): JSX.Element => {
); }; - -const mapStateToProps = (state: GlobalState) => { - return { - config: state.config.config, - }; -}; - -export default connect(mapStateToProps)(BookmarkCard); diff --git a/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx b/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx index 5162c89..848848b 100644 --- a/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx +++ b/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx @@ -8,94 +8,68 @@ import { } from 'react'; // Redux -import { connect } from 'react-redux'; -import { - getCategories, - addCategory, - addBookmark, - updateCategory, - updateBookmark, - createNotification, -} from '../../../store/actions'; +import { useDispatch, useSelector } from 'react-redux'; // Typescript import { Bookmark, Category, - GlobalState, NewBookmark, NewCategory, - NewNotification, } from '../../../interfaces'; import { ContentType } from '../Bookmarks'; // UI -import ModalForm from '../../UI/Forms/ModalForm/ModalForm'; -import InputGroup from '../../UI/Forms/InputGroup/InputGroup'; -import Button from '../../UI/Buttons/Button/Button'; +import { ModalForm, InputGroup, Button } from '../../UI'; // CSS import classes from './BookmarkForm.module.css'; +import { newBookmarkTemplate, newCategoryTemplate } from '../../../utility'; +import { State } from '../../../store/reducers'; +import { bindActionCreators } from 'redux'; +import { actionCreators } from '../../../store'; -interface ComponentProps { +interface Props { modalHandler: () => void; contentType: ContentType; - categories: Category[]; category?: Category; bookmark?: Bookmark; - addCategory: (formData: NewCategory) => void; - addBookmark: (formData: NewBookmark | FormData) => void; - updateCategory: (id: number, formData: NewCategory) => void; - updateBookmark: ( - id: number, - formData: NewBookmark | FormData, - category: { - prev: number; - curr: number; - } - ) => void; - createNotification: (notification: NewNotification) => void; } -const BookmarkForm = (props: ComponentProps): JSX.Element => { +export const BookmarkForm = (props: Props): JSX.Element => { + const { categories } = useSelector((state: State) => state.bookmarks); + + const dispatch = useDispatch(); + const { + addCategory, + addBookmark, + updateCategory, + updateBookmark, + createNotification, + } = bindActionCreators(actionCreators, dispatch); + const [useCustomIcon, toggleUseCustomIcon] = useState(false); const [customIcon, setCustomIcon] = useState(null); - const [categoryName, setCategoryName] = useState({ - name: '', - }); + const [categoryName, setCategoryName] = + useState(newCategoryTemplate); - const [formData, setFormData] = useState({ - name: '', - url: '', - categoryId: -1, - icon: '', - }); + const [formData, setFormData] = useState(newBookmarkTemplate); // Load category data if provided for editing useEffect(() => { if (props.category) { - setCategoryName({ name: props.category.name }); + setCategoryName({ ...props.category }); } else { - setCategoryName({ name: '' }); + setCategoryName(newCategoryTemplate); } }, [props.category]); // Load bookmark data if provided for editing useEffect(() => { if (props.bookmark) { - setFormData({ - name: props.bookmark.name, - url: props.bookmark.url, - categoryId: props.bookmark.categoryId, - icon: props.bookmark.icon, - }); + setFormData({ ...props.bookmark }); } else { - setFormData({ - name: '', - url: '', - categoryId: -1, - icon: '', - }); + setFormData(newBookmarkTemplate); } }, [props.bookmark]); @@ -118,12 +92,12 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { // Add new if (props.contentType === ContentType.category) { // Add category - props.addCategory(categoryName); - setCategoryName({ name: '' }); + addCategory(categoryName); + setCategoryName(newCategoryTemplate); } else if (props.contentType === ContentType.bookmark) { // Add bookmark if (formData.categoryId === -1) { - props.createNotification({ + createNotification({ title: 'Error', message: 'Please select category', }); @@ -132,16 +106,14 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { if (customIcon) { const data = createFormData(); - props.addBookmark(data); + addBookmark(data); } else { - props.addBookmark(formData); + addBookmark(formData); } setFormData({ - name: '', - url: '', + ...newBookmarkTemplate, categoryId: formData.categoryId, - icon: '', }); // setCustomIcon(null); @@ -150,29 +122,24 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { // Update if (props.contentType === ContentType.category && props.category) { // Update category - props.updateCategory(props.category.id, categoryName); - setCategoryName({ name: '' }); + updateCategory(props.category.id, categoryName); + setCategoryName(newCategoryTemplate); } else if (props.contentType === ContentType.bookmark && props.bookmark) { // Update bookmark if (customIcon) { const data = createFormData(); - props.updateBookmark(props.bookmark.id, data, { + updateBookmark(props.bookmark.id, data, { prev: props.bookmark.categoryId, curr: formData.categoryId, }); } else { - props.updateBookmark(props.bookmark.id, formData, { + updateBookmark(props.bookmark.id, formData, { prev: props.bookmark.categoryId, curr: formData.categoryId, }); } - setFormData({ - name: '', - url: '', - categoryId: -1, - icon: '', - }); + setFormData(newBookmarkTemplate); setCustomIcon(null); } @@ -231,7 +198,9 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { placeholder="Social Media" required value={categoryName.name} - onChange={(e) => setCategoryName({ name: e.target.value })} + onChange={(e) => + setCategoryName({ name: e.target.value, isPublic: !!!!!false }) + } /> @@ -249,6 +218,7 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { onChange={(e) => inputChangeHandler(e)} /> + { + + {!useCustomIcon ? ( // mdi @@ -344,20 +316,3 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { ); }; - -const mapStateToProps = (state: GlobalState) => { - return { - categories: state.bookmark.categories, - }; -}; - -const dispatchMap = { - getCategories, - addCategory, - addBookmark, - updateCategory, - updateBookmark, - createNotification, -}; - -export default connect(mapStateToProps, dispatchMap)(BookmarkForm); diff --git a/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.tsx b/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.tsx index bf17c81..cb4396f 100644 --- a/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.tsx +++ b/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.tsx @@ -4,15 +4,15 @@ import classes from './BookmarkGrid.module.css'; import { Category } from '../../../interfaces'; -import BookmarkCard from '../BookmarkCard/BookmarkCard'; +import { BookmarkCard } from '../BookmarkCard/BookmarkCard'; -interface ComponentProps { +interface Props { categories: Category[]; totalCategories?: number; searching: boolean; } -const BookmarkGrid = (props: ComponentProps): JSX.Element => { +export const BookmarkGrid = (props: Props): JSX.Element => { let bookmarks: JSX.Element; if (props.categories.length > 0) { @@ -53,5 +53,3 @@ const BookmarkGrid = (props: ComponentProps): JSX.Element => { return bookmarks; }; - -export default BookmarkGrid; diff --git a/client/src/components/Bookmarks/BookmarkTable/BookmarkTable.tsx b/client/src/components/Bookmarks/BookmarkTable/BookmarkTable.tsx index 90c34aa..7fd012a 100644 --- a/client/src/components/Bookmarks/BookmarkTable/BookmarkTable.tsx +++ b/client/src/components/Bookmarks/BookmarkTable/BookmarkTable.tsx @@ -8,45 +8,39 @@ import { import { Link } from 'react-router-dom'; // Redux -import { connect } from 'react-redux'; -import { - pinCategory, - deleteCategory, - deleteBookmark, - createNotification, - reorderCategories, -} from '../../../store/actions'; +import { useDispatch, useSelector } from 'react-redux'; +import { State } from '../../../store/reducers'; +import { bindActionCreators } from 'redux'; +import { actionCreators } from '../../../store'; // Typescript -import { - Bookmark, - Category, - Config, - GlobalState, - NewNotification, -} from '../../../interfaces'; +import { Bookmark, Category } from '../../../interfaces'; import { ContentType } from '../Bookmarks'; // CSS import classes from './BookmarkTable.module.css'; // UI -import Table from '../../UI/Table/Table'; -import Icon from '../../UI/Icons/Icon/Icon'; +import { Table, Icon } from '../../UI'; -interface ComponentProps { +interface Props { contentType: ContentType; categories: Category[]; - config: Config; - pinCategory: (category: Category) => void; - deleteCategory: (id: number) => void; updateHandler: (data: Category | Bookmark) => void; - deleteBookmark: (bookmarkId: number, categoryId: number) => void; - createNotification: (notification: NewNotification) => void; - reorderCategories: (categories: Category[]) => void; } -const BookmarkTable = (props: ComponentProps): JSX.Element => { +export const BookmarkTable = (props: Props): JSX.Element => { + const { config } = useSelector((state: State) => state.config); + + const dispatch = useDispatch(); + const { + pinCategory, + deleteCategory, + deleteBookmark, + createNotification, + reorderCategories, + } = bindActionCreators(actionCreators, dispatch); + const [localCategories, setLocalCategories] = useState([]); const [isCustomOrder, setIsCustomOrder] = useState(false); @@ -57,7 +51,7 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => { // Check ordering useEffect(() => { - const order = props.config.useOrdering; + const order = config.useOrdering; if (order === 'orderId') { setIsCustomOrder(true); @@ -70,7 +64,7 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => { ); if (proceed) { - props.deleteCategory(category.id); + deleteCategory(category.id); } }; @@ -80,7 +74,7 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => { ); if (proceed) { - props.deleteBookmark(bookmark.id, bookmark.categoryId); + deleteBookmark(bookmark.id, bookmark.categoryId); } }; @@ -96,7 +90,7 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => { const dragEndHanlder = (result: DropResult): void => { if (!isCustomOrder) { - props.createNotification({ + createNotification({ title: 'Error', message: 'Custom order is disabled', }); @@ -112,7 +106,7 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => { tmpCategories.splice(result.destination.index, 0, movedApp); setLocalCategories(tmpCategories); - props.reorderCategories(tmpCategories); + reorderCategories(tmpCategories); }; if (props.contentType === ContentType.category) { @@ -186,12 +180,12 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => {
props.pinCategory(category)} + onClick={() => pinCategory(category)} onKeyDown={(e) => keyboardActionHandler( e, category, - props.pinCategory + pinCategory ) } tabIndex={0} @@ -265,19 +259,3 @@ const BookmarkTable = (props: ComponentProps): JSX.Element => { ); } }; - -const mapStateToProps = (state: GlobalState) => { - return { - config: state.config.config, - }; -}; - -const actions = { - pinCategory, - deleteCategory, - deleteBookmark, - createNotification, - reorderCategories, -}; - -export default connect(mapStateToProps, actions)(BookmarkTable); diff --git a/client/src/components/Bookmarks/Bookmarks.tsx b/client/src/components/Bookmarks/Bookmarks.tsx index 88d9cdb..fffb5ff 100644 --- a/client/src/components/Bookmarks/Bookmarks.tsx +++ b/client/src/components/Bookmarks/Bookmarks.tsx @@ -1,25 +1,30 @@ import { useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; -import { connect } from 'react-redux'; -import { getCategories } from '../../store/actions'; +// Redux +import { useDispatch, useSelector } from 'react-redux'; +import { State } from '../../store/reducers'; +import { bindActionCreators } from 'redux'; +import { actionCreators } from '../../store'; + +// Typescript +import { Category, Bookmark } from '../../interfaces'; + +// CSS import classes from './Bookmarks.module.css'; -import { Container } from '../UI/Layout/Layout'; -import Headline from '../UI/Headlines/Headline/Headline'; -import ActionButton from '../UI/Buttons/ActionButton/ActionButton'; +// UI +import { Container, Headline, ActionButton, Spinner, Modal } from '../UI'; -import BookmarkGrid from './BookmarkGrid/BookmarkGrid'; -import { Category, GlobalState, Bookmark } from '../../interfaces'; -import Spinner from '../UI/Spinner/Spinner'; -import Modal from '../UI/Modal/Modal'; -import BookmarkForm from './BookmarkForm/BookmarkForm'; -import BookmarkTable from './BookmarkTable/BookmarkTable'; +// Components +import { BookmarkGrid } from './BookmarkGrid/BookmarkGrid'; +import { BookmarkForm } from './BookmarkForm/BookmarkForm'; +import { BookmarkTable } from './BookmarkTable/BookmarkTable'; -interface ComponentProps { - loading: boolean; - categories: Category[]; - getCategories: () => void; +// Utils +import { bookmarkTemplate, categoryTemplate } from '../../utility'; + +interface Props { searching: boolean; } @@ -28,8 +33,15 @@ export enum ContentType { bookmark, } -const Bookmarks = (props: ComponentProps): JSX.Element => { - const { getCategories, categories, loading, searching = false } = props; +export const Bookmarks = (props: Props): JSX.Element => { + const { loading, categories } = useSelector( + (state: State) => state.bookmarks + ); + + const dispatch = useDispatch(); + const { getCategories } = bindActionCreators(actionCreators, dispatch); + + const { searching = false } = props; const [modalIsOpen, setModalIsOpen] = useState(false); const [formContentType, setFormContentType] = useState(ContentType.category); @@ -38,24 +50,10 @@ const Bookmarks = (props: ComponentProps): JSX.Element => { ContentType.category ); const [isInUpdate, setIsInUpdate] = useState(false); - const [categoryInUpdate, setCategoryInUpdate] = useState({ - name: '', - id: -1, - isPinned: false, - orderId: 0, - bookmarks: [], - createdAt: new Date(), - updatedAt: new Date(), - }); - const [bookmarkInUpdate, setBookmarkInUpdate] = useState({ - name: '', - url: '', - categoryId: -1, - icon: '', - id: -1, - createdAt: new Date(), - updatedAt: new Date(), - }); + const [categoryInUpdate, setCategoryInUpdate] = + useState(categoryTemplate); + const [bookmarkInUpdate, setBookmarkInUpdate] = + useState(bookmarkTemplate); useEffect(() => { if (categories.length === 0) { @@ -161,12 +159,3 @@ const Bookmarks = (props: ComponentProps): JSX.Element => { ); }; - -const mapStateToProps = (state: GlobalState) => { - return { - loading: state.bookmark.loading, - categories: state.bookmark.categories, - }; -}; - -export default connect(mapStateToProps, { getCategories })(Bookmarks); diff --git a/client/src/components/Home/Header/Header.tsx b/client/src/components/Home/Header/Header.tsx index 3b2841b..f059b49 100644 --- a/client/src/components/Home/Header/Header.tsx +++ b/client/src/components/Home/Header/Header.tsx @@ -1,17 +1,17 @@ import { useEffect, useState } from 'react'; -import { connect } from 'react-redux'; import { Link } from 'react-router-dom'; -import { Config, GlobalState } from '../../../interfaces'; -import WeatherWidget from '../../Widgets/WeatherWidget/WeatherWidget'; -import { getDateTime } from './functions/getDateTime'; -import { greeter } from './functions/greeter'; + +// CSS import classes from './Header.module.css'; -interface Props { - config: Config; -} +// Components +import { WeatherWidget } from '../../Widgets/WeatherWidget/WeatherWidget'; -const Header = (props: Props): JSX.Element => { +// Utils +import { getDateTime } from './functions/getDateTime'; +import { greeter } from './functions/greeter'; + +export const Header = (): JSX.Element => { const [dateTime, setDateTime] = useState(getDateTime()); const [greeting, setGreeting] = useState(greeter()); @@ -39,11 +39,3 @@ const Header = (props: Props): JSX.Element => { ); }; - -const mapStateToProps = (state: GlobalState) => { - return { - config: state.config.config, - }; -}; - -export default connect(mapStateToProps)(Header); diff --git a/client/src/components/Home/Home.tsx b/client/src/components/Home/Home.tsx index 017df9c..578054c 100644 --- a/client/src/components/Home/Home.tsx +++ b/client/src/components/Home/Home.tsx @@ -2,47 +2,38 @@ import { useState, useEffect, Fragment } from 'react'; import { Link } from 'react-router-dom'; // Redux -import { connect } from 'react-redux'; -import { getApps, getCategories } from '../../store/actions'; +import { useDispatch, useSelector } from 'react-redux'; +import { State } from '../../store/reducers'; +import { bindActionCreators } from 'redux'; +import { actionCreators } from '../../store'; // Typescript -import { GlobalState } from '../../interfaces/GlobalState'; -import { App, Category, Config } from '../../interfaces'; +import { App, Category } from '../../interfaces'; // UI -import Icon from '../UI/Icons/Icon/Icon'; -import { Container } from '../UI/Layout/Layout'; -import SectionHeadline from '../UI/Headlines/SectionHeadline/SectionHeadline'; -import Spinner from '../UI/Spinner/Spinner'; +import { Icon, Container, SectionHeadline, Spinner } from '../UI'; // CSS import classes from './Home.module.css'; // Components -import AppGrid from '../Apps/AppGrid/AppGrid'; -import BookmarkGrid from '../Bookmarks/BookmarkGrid/BookmarkGrid'; -import SearchBar from '../SearchBar/SearchBar'; -import Header from './Header/Header'; +import { AppGrid } from '../Apps/AppGrid/AppGrid'; +import { BookmarkGrid } from '../Bookmarks/BookmarkGrid/BookmarkGrid'; +import { SearchBar } from '../SearchBar/SearchBar'; +import { Header } from './Header/Header'; -interface ComponentProps { - getApps: Function; - getCategories: Function; - appsLoading: boolean; - apps: App[]; - categoriesLoading: boolean; - categories: Category[]; - config: Config; -} - -const Home = (props: ComponentProps): JSX.Element => { +export const Home = (): JSX.Element => { const { - getApps, - apps, - appsLoading, - getCategories, - categories, - categoriesLoading, - } = props; + apps: { apps, loading: appsLoading }, + bookmarks: { categories, loading: bookmarksLoading }, + config: { config }, + } = useSelector((state: State) => state); + + const dispatch = useDispatch(); + const { getApps, getCategories } = bindActionCreators( + actionCreators, + dispatch + ); // Local search query const [localSearch, setLocalSearch] = useState(null); @@ -90,7 +81,7 @@ const Home = (props: ComponentProps): JSX.Element => { return ( - {!props.config.hideSearch ? ( + {!config.hideSearch ? ( {
)} - {!props.config.hideHeader ?
:
} + {!config.hideHeader ?
:
} - {!props.config.hideApps ? ( + {!config.hideApps ? ( {appsLoading ? ( @@ -124,10 +115,10 @@ const Home = (props: ComponentProps): JSX.Element => {
)} - {!props.config.hideCategories ? ( + {!config.hideCategories ? ( - {categoriesLoading ? ( + {bookmarksLoading ? ( ) : ( { ); }; - -const mapStateToProps = (state: GlobalState) => { - return { - appsLoading: state.app.loading, - apps: state.app.apps, - categoriesLoading: state.bookmark.loading, - categories: state.bookmark.categories, - config: state.config.config, - }; -}; - -export default connect(mapStateToProps, { getApps, getCategories })(Home); diff --git a/client/src/components/NotificationCenter/NotificationCenter.tsx b/client/src/components/NotificationCenter/NotificationCenter.tsx index 733316b..4bda8bf 100644 --- a/client/src/components/NotificationCenter/NotificationCenter.tsx +++ b/client/src/components/NotificationCenter/NotificationCenter.tsx @@ -1,21 +1,20 @@ -import { connect } from 'react-redux'; -import { GlobalState, Notification as _Notification } from '../../interfaces'; +import { useSelector } from 'react-redux'; +import { Notification as NotificationInterface } from '../../interfaces'; import classes from './NotificationCenter.module.css'; -import Notification from '../UI/Notification/Notification'; +import { Notification } from '../UI'; +import { State } from '../../store/reducers'; -interface ComponentProps { - notifications: _Notification[]; -} +export const NotificationCenter = (): JSX.Element => { + const { notifications } = useSelector((state: State) => state.notification); -const NotificationCenter = (props: ComponentProps): JSX.Element => { return (
- {props.notifications.map((notification: _Notification) => { + {notifications.map((notification: NotificationInterface) => { return ( {
); }; - -const mapStateToProps = (state: GlobalState) => { - return { - notifications: state.notification.notifications, - }; -}; - -export default connect(mapStateToProps)(NotificationCenter); diff --git a/client/src/components/SearchBar/SearchBar.tsx b/client/src/components/SearchBar/SearchBar.tsx index 2dad112..46f0bfd 100644 --- a/client/src/components/SearchBar/SearchBar.tsx +++ b/client/src/components/SearchBar/SearchBar.tsx @@ -1,42 +1,33 @@ import { useRef, useEffect, KeyboardEvent } from 'react'; // Redux -import { connect } from 'react-redux'; -import { createNotification } from '../../store/actions'; +import { useDispatch, useSelector } from 'react-redux'; // Typescript -import { - App, - Category, - Config, - GlobalState, - NewNotification, -} from '../../interfaces'; +import { App, Category } from '../../interfaces'; // CSS import classes from './SearchBar.module.css'; // Utils import { searchParser, urlParser, redirectUrl } from '../../utility'; +import { State } from '../../store/reducers'; +import { bindActionCreators } from 'redux'; +import { actionCreators } from '../../store'; -interface ComponentProps { - createNotification: (notification: NewNotification) => void; +interface Props { setLocalSearch: (query: string) => void; appSearchResult: App[] | null; bookmarkSearchResult: Category[] | null; - config: Config; - loading: boolean; } -const SearchBar = (props: ComponentProps): JSX.Element => { - const { - setLocalSearch, - createNotification, - config, - loading, - appSearchResult, - bookmarkSearchResult, - } = props; +export const SearchBar = (props: Props): JSX.Element => { + const { config, loading } = useSelector((state: State) => state.config); + + const dispatch = useDispatch(); + const { createNotification } = bindActionCreators(actionCreators, dispatch); + + const { setLocalSearch, appSearchResult, bookmarkSearchResult } = props; const inputRef = useRef(document.createElement('input')); @@ -126,12 +117,3 @@ const SearchBar = (props: ComponentProps): JSX.Element => {
); }; - -const mapStateToProps = (state: GlobalState) => { - return { - config: state.config.config, - loading: state.config.loading, - }; -}; - -export default connect(mapStateToProps, { createNotification })(SearchBar); diff --git a/client/src/components/Settings/AppDetails/AppDetails.tsx b/client/src/components/Settings/AppDetails/AppDetails.tsx index 109053a..42257ed 100644 --- a/client/src/components/Settings/AppDetails/AppDetails.tsx +++ b/client/src/components/Settings/AppDetails/AppDetails.tsx @@ -1,34 +1,33 @@ import { Fragment } from 'react'; import classes from './AppDetails.module.css'; -import Button from '../../UI/Buttons/Button/Button'; +import { Button } from '../../UI'; import { checkVersion } from '../../../utility'; -const AppDetails = (): JSX.Element => { +export const AppDetails = (): JSX.Element => { return (

+ href="https://github.com/pawelmalak/flame" + target="_blank" + rel="noreferrer" + > Flame - - {' '} + {' '} version {process.env.REACT_APP_VERSION}

- See changelog {' '} + See changelog{' '} + href="https://github.com/pawelmalak/flame/blob/master/CHANGELOG.md" + target="_blank" + rel="noreferrer" + > here

- ) -} - -export default AppDetails; + ); +}; diff --git a/client/src/components/Settings/OtherSettings/OtherSettings.tsx b/client/src/components/Settings/OtherSettings/OtherSettings.tsx index c5b45ae..3ec317f 100644 --- a/client/src/components/Settings/OtherSettings/OtherSettings.tsx +++ b/client/src/components/Settings/OtherSettings/OtherSettings.tsx @@ -1,41 +1,28 @@ import { useState, useEffect, ChangeEvent, FormEvent } from 'react'; // Redux -import { connect } from 'react-redux'; -import { - createNotification, - updateConfig, - sortApps, - sortCategories, -} from '../../../store/actions'; +import { useDispatch, useSelector } from 'react-redux'; // Typescript -import { - Config, - GlobalState, - NewNotification, - OtherSettingsForm, -} from '../../../interfaces'; +import { OtherSettingsForm } from '../../../interfaces'; // UI -import InputGroup from '../../UI/Forms/InputGroup/InputGroup'; -import Button from '../../UI/Buttons/Button/Button'; -import SettingsHeadline from '../../UI/Headlines/SettingsHeadline/SettingsHeadline'; +import { InputGroup, Button, SettingsHeadline } from '../../UI'; // Utils import { otherSettingsTemplate, inputHandler } from '../../../utility'; +import { State } from '../../../store/reducers'; +import { bindActionCreators } from 'redux'; +import { actionCreators } from '../../../store'; -interface ComponentProps { - createNotification: (notification: NewNotification) => void; - updateConfig: (formData: OtherSettingsForm) => void; - sortApps: () => void; - sortCategories: () => void; - loading: boolean; - config: Config; -} +export const OtherSettings = (): JSX.Element => { + const { loading, config } = useSelector((state: State) => state.config); -const OtherSettings = (props: ComponentProps): JSX.Element => { - const { config } = props; + const dispatch = useDispatch(); + const { updateConfig, sortApps, sortCategories } = bindActionCreators( + actionCreators, + dispatch + ); // Initial state const [formData, setFormData] = useState( @@ -47,21 +34,21 @@ const OtherSettings = (props: ComponentProps): JSX.Element => { setFormData({ ...config, }); - }, [props.loading]); + }, [loading]); // Form handler const formSubmitHandler = async (e: FormEvent) => { e.preventDefault(); // Save settings - await props.updateConfig(formData); + await updateConfig(formData); // Update local page title document.title = formData.customTitle; // Sort apps and categories with new settings - props.sortApps(); - props.sortCategories(); + sortApps(); + sortCategories(); }; // Input handler @@ -338,19 +325,3 @@ const OtherSettings = (props: ComponentProps): JSX.Element => { ); }; - -const mapStateToProps = (state: GlobalState) => { - return { - loading: state.config.loading, - config: state.config.config, - }; -}; - -const actions = { - createNotification, - updateConfig, - sortApps, - sortCategories, -}; - -export default connect(mapStateToProps, actions)(OtherSettings); diff --git a/client/src/components/Settings/SearchSettings/CustomQueries/CustomQueries.tsx b/client/src/components/Settings/SearchSettings/CustomQueries/CustomQueries.tsx index a694f42..747be3b 100644 --- a/client/src/components/Settings/SearchSettings/CustomQueries/CustomQueries.tsx +++ b/client/src/components/Settings/SearchSettings/CustomQueries/CustomQueries.tsx @@ -1,29 +1,31 @@ import { Fragment, useState } from 'react'; -import { connect } from 'react-redux'; +// Redux +import { useDispatch, useSelector } from 'react-redux'; +import { State } from '../../../../store/reducers'; +import { bindActionCreators } from 'redux'; +import { actionCreators } from '../../../../store'; + +// Typescript +import { Query } from '../../../../interfaces'; + +// CSS import classes from './CustomQueries.module.css'; -import Modal from '../../../UI/Modal/Modal'; -import Icon from '../../../UI/Icons/Icon/Icon'; -import { - Config, - GlobalState, - NewNotification, - Query, -} from '../../../../interfaces'; -import QueriesForm from './QueriesForm'; -import { deleteQuery, createNotification } from '../../../../store/actions'; -import Button from '../../../UI/Buttons/Button/Button'; +// UI +import { Modal, Icon, Button } from '../../../UI'; -interface Props { - customQueries: Query[]; - deleteQuery: (prefix: string) => {}; - createNotification: (notification: NewNotification) => void; - config: Config; -} +// Components +import { QueriesForm } from './QueriesForm'; -const CustomQueries = (props: Props): JSX.Element => { - const { customQueries, deleteQuery, createNotification } = props; +export const CustomQueries = (): JSX.Element => { + const { customQueries, config } = useSelector((state: State) => state.config); + + const dispatch = useDispatch(); + const { deleteQuery, createNotification } = bindActionCreators( + actionCreators, + dispatch + ); const [modalIsOpen, setModalIsOpen] = useState(false); const [editableQuery, setEditableQuery] = useState(null); @@ -34,7 +36,7 @@ const CustomQueries = (props: Props): JSX.Element => { }; const deleteHandler = (query: Query) => { - const currentProvider = props.config.defaultSearchProvider; + const currentProvider = config.defaultSearchProvider; const isCurrent = currentProvider === query.prefix; if (isCurrent) { @@ -105,14 +107,3 @@ const CustomQueries = (props: Props): JSX.Element => { ); }; - -const mapStateToProps = (state: GlobalState) => { - return { - customQueries: state.config.customQueries, - config: state.config.config, - }; -}; - -export default connect(mapStateToProps, { deleteQuery, createNotification })( - CustomQueries -); diff --git a/client/src/components/Settings/SearchSettings/CustomQueries/QueriesForm.tsx b/client/src/components/Settings/SearchSettings/CustomQueries/QueriesForm.tsx index 42ad654..2cb76a9 100644 --- a/client/src/components/Settings/SearchSettings/CustomQueries/QueriesForm.tsx +++ b/client/src/components/Settings/SearchSettings/CustomQueries/QueriesForm.tsx @@ -1,20 +1,26 @@ import { ChangeEvent, FormEvent, useState, useEffect } from 'react'; + +import { useDispatch } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import { actionCreators } from '../../../../store'; + import { Query } from '../../../../interfaces'; -import Button from '../../../UI/Buttons/Button/Button'; -import InputGroup from '../../../UI/Forms/InputGroup/InputGroup'; -import ModalForm from '../../../UI/Forms/ModalForm/ModalForm'; -import { connect } from 'react-redux'; -import { addQuery, updateQuery } from '../../../../store/actions'; + +import { Button, InputGroup, ModalForm } from '../../../UI'; interface Props { modalHandler: () => void; - addQuery: (query: Query) => {}; - updateQuery: (query: Query, Oldprefix: string) => {}; query?: Query; } -const QueriesForm = (props: Props): JSX.Element => { - const { modalHandler, addQuery, updateQuery, query } = props; +export const QueriesForm = (props: Props): JSX.Element => { + const dispatch = useDispatch(); + const { addQuery, updateQuery } = bindActionCreators( + actionCreators, + dispatch + ); + + const { modalHandler, query } = props; const [formData, setFormData] = useState({ name: '', @@ -77,6 +83,7 @@ const QueriesForm = (props: Props): JSX.Element => { onChange={(e) => inputChangeHandler(e)} /> + { onChange={(e) => inputChangeHandler(e)} /> + { onChange={(e) => inputChangeHandler(e)} /> + {query ? : } ); }; - -export default connect(null, { addQuery, updateQuery })(QueriesForm); diff --git a/client/src/components/Settings/SearchSettings/SearchSettings.tsx b/client/src/components/Settings/SearchSettings/SearchSettings.tsx index d05def5..2717b43 100644 --- a/client/src/components/Settings/SearchSettings/SearchSettings.tsx +++ b/client/src/components/Settings/SearchSettings/SearchSettings.tsx @@ -1,58 +1,49 @@ // React import { useState, useEffect, FormEvent, ChangeEvent, Fragment } from 'react'; -import { connect } from 'react-redux'; - -// State -import { createNotification, updateConfig } from '../../../store/actions'; +import { useDispatch, useSelector } from 'react-redux'; // Typescript -import { - Config, - GlobalState, - NewNotification, - Query, - SearchForm, -} from '../../../interfaces'; +import { Query, SearchForm } from '../../../interfaces'; // Components -import CustomQueries from './CustomQueries/CustomQueries'; +import { CustomQueries } from './CustomQueries/CustomQueries'; // UI -import Button from '../../UI/Buttons/Button/Button'; -import SettingsHeadline from '../../UI/Headlines/SettingsHeadline/SettingsHeadline'; -import InputGroup from '../../UI/Forms/InputGroup/InputGroup'; +import { Button, SettingsHeadline, InputGroup } from '../../UI'; // Utils import { inputHandler, searchSettingsTemplate } from '../../../utility'; // Data import { queries } from '../../../utility/searchQueries.json'; +import { State } from '../../../store/reducers'; +import { bindActionCreators } from 'redux'; +import { actionCreators } from '../../../store'; -interface Props { - createNotification: (notification: NewNotification) => void; - updateConfig: (formData: SearchForm) => void; - loading: boolean; - customQueries: Query[]; - config: Config; -} +export const SearchSettings = (): JSX.Element => { + const { loading, customQueries, config } = useSelector( + (state: State) => state.config + ); + + const dispatch = useDispatch(); + const { updateConfig } = bindActionCreators(actionCreators, dispatch); -const SearchSettings = (props: Props): JSX.Element => { // Initial state const [formData, setFormData] = useState(searchSettingsTemplate); // Get config useEffect(() => { setFormData({ - ...props.config, + ...config, }); - }, [props.loading]); + }, [loading]); // Form handler const formSubmitHandler = async (e: FormEvent) => { e.preventDefault(); // Save settings - await props.updateConfig(formData); + await updateConfig(formData); }; // Input handler @@ -84,7 +75,7 @@ const SearchSettings = (props: Props): JSX.Element => { value={formData.defaultSearchProvider} onChange={(e) => inputChangeHandler(e)} > - {[...queries, ...props.customQueries].map((query: Query, idx) => { + {[...queries, ...customQueries].map((query: Query, idx) => { const isCustom = idx >= queries.length; return ( @@ -95,6 +86,7 @@ const SearchSettings = (props: Props): JSX.Element => { })} + + + + @@ -142,18 +137,3 @@ const SearchSettings = (props: Props): JSX.Element => { ); }; - -const mapStateToProps = (state: GlobalState) => { - return { - loading: state.config.loading, - customQueries: state.config.customQueries, - config: state.config.config, - }; -}; - -const actions = { - createNotification, - updateConfig, -}; - -export default connect(mapStateToProps, actions)(SearchSettings); diff --git a/client/src/components/Settings/Settings.tsx b/client/src/components/Settings/Settings.tsx index 5df8ec6..0c53693 100644 --- a/client/src/components/Settings/Settings.tsx +++ b/client/src/components/Settings/Settings.tsx @@ -1,4 +1,3 @@ -// import { NavLink, Link, Switch, Route } from 'react-router-dom'; // Typescript @@ -8,21 +7,20 @@ import { Route as SettingsRoute } from '../../interfaces'; import classes from './Settings.module.css'; // Components -import Themer from '../Themer/Themer'; -import WeatherSettings from './WeatherSettings/WeatherSettings'; -import OtherSettings from './OtherSettings/OtherSettings'; -import AppDetails from './AppDetails/AppDetails'; -import StyleSettings from './StyleSettings/StyleSettings'; -import SearchSettings from './SearchSettings/SearchSettings'; +import { Themer } from '../Themer/Themer'; +import { WeatherSettings } from './WeatherSettings/WeatherSettings'; +import { OtherSettings } from './OtherSettings/OtherSettings'; +import { AppDetails } from './AppDetails/AppDetails'; +import { StyleSettings } from './StyleSettings/StyleSettings'; +import { SearchSettings } from './SearchSettings/SearchSettings'; // UI -import { Container } from '../UI/Layout/Layout'; -import Headline from '../UI/Headlines/Headline/Headline'; +import { Container, Headline } from '../UI'; // Data import { routes } from './settings.json'; -const Settings = (): JSX.Element => { +export const Settings = (): JSX.Element => { return ( Go back} /> @@ -57,5 +55,3 @@ const Settings = (): JSX.Element => { ); }; - -export default Settings; diff --git a/client/src/components/Settings/StyleSettings/StyleSettings.tsx b/client/src/components/Settings/StyleSettings/StyleSettings.tsx index 9f45065..b2d7c8e 100644 --- a/client/src/components/Settings/StyleSettings/StyleSettings.tsx +++ b/client/src/components/Settings/StyleSettings/StyleSettings.tsx @@ -2,54 +2,55 @@ import { useState, useEffect, ChangeEvent, FormEvent } from 'react'; import axios from 'axios'; // Redux -import { connect } from 'react-redux'; -import { createNotification } from '../../../store/actions'; +import { useDispatch } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import { actionCreators } from '../../../store'; // Typescript -import { ApiResponse, NewNotification } from '../../../interfaces'; +import { ApiResponse } from '../../../interfaces'; // UI -import InputGroup from '../../UI/Forms/InputGroup/InputGroup'; -import Button from '../../UI/Buttons/Button/Button'; +import { InputGroup, Button } from '../../UI'; -interface ComponentProps { - createNotification: (notification: NewNotification) => void; -} +export const StyleSettings = (): JSX.Element => { + const dispatch = useDispatch(); + const { createNotification } = bindActionCreators(actionCreators, dispatch); -const StyleSettings = (props: ComponentProps): JSX.Element => { const [customStyles, setCustomStyles] = useState(''); useEffect(() => { - axios.get>('/api/config/0/css') - .then(data => setCustomStyles(data.data.data)) - .catch(err => console.log(err.response)); - }, []) + axios + .get>('/api/config/0/css') + .then((data) => setCustomStyles(data.data.data)) + .catch((err) => console.log(err.response)); + }, []); const inputChangeHandler = (e: ChangeEvent) => { e.preventDefault(); setCustomStyles(e.target.value); - } + }; const formSubmitHandler = (e: FormEvent) => { e.preventDefault(); - axios.put>('/api/config/0/css', { styles: customStyles }) + axios + .put>('/api/config/0/css', { styles: customStyles }) .then(() => { - props.createNotification({ + createNotification({ title: 'Success', - message: 'CSS saved. Reload page to see changes' - }) + message: 'CSS saved. Reload page to see changes', + }); }) - .catch(err => console.log(err.response)); - } + .catch((err) => console.log(err.response)); + }; return (
formSubmitHandler(e)}> - +