diff --git a/README.md b/README.md index 25d7436..d61baa6 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ docker run -p 5005:5005 -v :/app/data flame ![Homescreen screenshot](./github/_themes.png) ## Usage -### Supported links for applications and bookmarks +### Supported URL formats for applications and bookmarks #### Rules - URL starts with `http://` - Format: `http://www.domain.com`, `http://domain.com` diff --git a/client/src/App.module.css b/client/src/App.module.css deleted file mode 100644 index e69de29..0000000 diff --git a/client/src/App.tsx b/client/src/App.tsx index efdf4c8..d58f4ad 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -5,8 +5,6 @@ import { getConfig, setTheme } from './store/actions'; import { store } from './store/store'; import { Provider } from 'react-redux'; -import classes from './App.module.css'; - import Home from './components/Home/Home'; import Apps from './components/Apps/Apps'; import Settings from './components/Settings/Settings'; diff --git a/client/src/components/Apps/AppCard/AppCard.tsx b/client/src/components/Apps/AppCard/AppCard.tsx index d2ef375..50fb979 100644 --- a/client/src/components/Apps/AppCard/AppCard.tsx +++ b/client/src/components/Apps/AppCard/AppCard.tsx @@ -13,7 +13,12 @@ const AppCard = (props: ComponentProps): JSX.Element => { const [displayUrl, redirectUrl] = urlParser(props.app.url); return ( - +
diff --git a/client/src/components/Apps/AppForm/AppForm.tsx b/client/src/components/Apps/AppForm/AppForm.tsx index b833752..cffeb19 100644 --- a/client/src/components/Apps/AppForm/AppForm.tsx +++ b/client/src/components/Apps/AppForm/AppForm.tsx @@ -98,7 +98,15 @@ const AppForm = (props: ComponentProps): JSX.Element => { value={formData.url} onChange={(e) => inputChangeHandler(e)} /> - Only urls without http[s]:// are supported + +
+ {' '}Check supported URL formats + + diff --git a/client/src/components/Apps/Apps.tsx b/client/src/components/Apps/Apps.tsx index 0f8e079..f02fba6 100644 --- a/client/src/components/Apps/Apps.tsx +++ b/client/src/components/Apps/Apps.tsx @@ -1,4 +1,4 @@ -import { Fragment, useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; // Redux @@ -30,6 +30,12 @@ interface ComponentProps { } const Apps = (props: ComponentProps): JSX.Element => { + const { + getApps, + apps, + loading + } = props; + const [modalIsOpen, setModalIsOpen] = useState(false); const [isInEdit, setIsInEdit] = useState(false); const [isInUpdate, setIsInUpdate] = useState(false); @@ -44,10 +50,10 @@ const Apps = (props: ComponentProps): JSX.Element => { }) useEffect(() => { - if (props.apps.length === 0) { - props.getApps(); + if (apps.length === 0) { + getApps(); } - }, [props.getApps]); + }, [getApps, apps]); const toggleModal = (): void => { setModalIsOpen(!modalIsOpen); @@ -93,10 +99,10 @@ const Apps = (props: ComponentProps): JSX.Element => {
- {props.loading + {loading ? : (!isInEdit - ? + ? : ) }
diff --git a/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.tsx b/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.tsx index 6ddf0b7..9e8dff9 100644 --- a/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.tsx +++ b/client/src/components/Bookmarks/BookmarkCard/BookmarkCard.tsx @@ -14,12 +14,13 @@ const BookmarkCard = (props: ComponentProps): JSX.Element => {

{props.category.name}

{props.category.bookmarks.map((bookmark: Bookmark) => { - const [displayUrl, redirectUrl] = urlParser(bookmark.url); + const redirectUrl = urlParser(bookmark.url)[1]; return ( {bookmark.icon && (
diff --git a/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx b/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx index c5f5bcf..9341565 100644 --- a/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx +++ b/client/src/components/Bookmarks/BookmarkForm/BookmarkForm.tsx @@ -184,7 +184,15 @@ const BookmarkForm = (props: ComponentProps): JSX.Element => { value={formData.url} onChange={(e) => inputChangeHandler(e)} /> - Only urls without http[s]:// are supported + + + {' '}Check supported URL formats + + diff --git a/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.tsx b/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.tsx index c6355c6..c316f31 100644 --- a/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.tsx +++ b/client/src/components/Bookmarks/BookmarkGrid/BookmarkGrid.tsx @@ -2,7 +2,7 @@ import { Link } from 'react-router-dom'; import classes from './BookmarkGrid.module.css'; -import { Bookmark, Category } from '../../../interfaces'; +import { Category } from '../../../interfaces'; import BookmarkCard from '../BookmarkCard/BookmarkCard'; diff --git a/client/src/components/Bookmarks/Bookmarks.tsx b/client/src/components/Bookmarks/Bookmarks.tsx index 53cca5c..b386706 100644 --- a/client/src/components/Bookmarks/Bookmarks.tsx +++ b/client/src/components/Bookmarks/Bookmarks.tsx @@ -28,6 +28,12 @@ export enum ContentType { } const Bookmarks = (props: ComponentProps): JSX.Element => { + const { + getCategories, + categories, + loading + } = props; + const [modalIsOpen, setModalIsOpen] = useState(false); const [formContentType, setFormContentType] = useState(ContentType.category); const [isInEdit, setIsInEdit] = useState(false); @@ -52,10 +58,10 @@ const Bookmarks = (props: ComponentProps): JSX.Element => { }) useEffect(() => { - if (props.categories.length === 0) { - props.getCategories(); + if (categories.length === 0) { + getCategories(); } - }, [props.getCategories]) + }, [getCategories, categories]) const toggleModal = (): void => { setModalIsOpen(!modalIsOpen); @@ -132,13 +138,13 @@ const Bookmarks = (props: ComponentProps): JSX.Element => { />
- {props.loading + {loading ? : (!isInEdit - ? + ? : ) diff --git a/client/src/components/Home/Home.tsx b/client/src/components/Home/Home.tsx index 1fdd090..ab41ac2 100644 --- a/client/src/components/Home/Home.tsx +++ b/client/src/components/Home/Home.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; // Redux @@ -23,6 +23,10 @@ import AppGrid from '../Apps/AppGrid/AppGrid'; import BookmarkGrid from '../Bookmarks/BookmarkGrid/BookmarkGrid'; import WeatherWidget from '../Widgets/WeatherWidget/WeatherWidget'; +// Functions +import { greeter } from './functions/greeter'; +import { dateTime } from './functions/dateTime'; + interface ComponentProps { getApps: Function; getCategories: Function; @@ -33,68 +37,74 @@ interface ComponentProps { } const Home = (props: ComponentProps): JSX.Element => { + const { + getApps, + apps, + appsLoading, + getCategories, + categories, + categoriesLoading + } = props; + + const [header, setHeader] = useState({ + dateTime: dateTime(), + greeting: greeter() + }) + + // Load applications useEffect(() => { - if (props.apps.length === 0) { - props.getApps(); + if (apps.length === 0) { + getApps(); } - }, [props.getApps]); + }, [getApps, apps]); + // Load bookmark categories useEffect(() => { - if (props.categories.length === 0) { - props.getCategories(); + if (categories.length === 0) { + getCategories(); } - }, [props.getCategories]); + }, [getCategories, categories]); - const dateAndTime = (): string => { - const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; - const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + // Refresh greeter and time + useEffect(() => { + const interval = setInterval(() => { + setHeader({ + dateTime: dateTime(), + greeting: greeter() + }) + }, 1000); - const now = new Date(); - - return `${days[now.getDay()]}, ${now.getDate()} ${months[now.getMonth()]} ${now.getFullYear()}`; - } - - const greeter = (): string => { - const now = new Date().getHours(); - let msg: string; - - if (now >= 18) msg = 'Good evening!'; - else if (now >= 12) msg = 'Good afternoon!'; - else if (now >= 6) msg = 'Good morning!'; - else if (now >= 0) msg = 'Good night!'; - else msg = 'Hello!'; - - return msg; - } + return () => clearInterval(interval); + }, []) return (
-

{dateAndTime()}

+

{header.dateTime}

Go to Settings -

{greeter()}

+

{header.greeting}

- {props.appsLoading + {appsLoading ? : app.isPinned)} - totalApps={props.apps.length} + apps={apps.filter((app: App) => app.isPinned)} + totalApps={apps.length} /> }
- {props.categoriesLoading + {categoriesLoading ? : category.isPinned)} - totalCategories={props.categories.length} + categories={categories.filter((category: Category) => category.isPinned)} + totalCategories={categories.length} /> } diff --git a/client/src/components/Home/functions/dateTime.ts b/client/src/components/Home/functions/dateTime.ts new file mode 100644 index 0000000..44cc5e1 --- /dev/null +++ b/client/src/components/Home/functions/dateTime.ts @@ -0,0 +1,8 @@ +export const dateTime = (): string => { + const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; + const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + + const now = new Date(); + + return `${days[now.getDay()]}, ${now.getDate()} ${months[now.getMonth()]} ${now.getFullYear()}`; +} \ No newline at end of file diff --git a/client/src/components/Home/functions/greeter.ts b/client/src/components/Home/functions/greeter.ts new file mode 100644 index 0000000..64cb2ea --- /dev/null +++ b/client/src/components/Home/functions/greeter.ts @@ -0,0 +1,12 @@ +export const greeter = (): string => { + const now = new Date().getHours(); + let msg: string; + + if (now >= 18) msg = 'Good evening!'; + else if (now >= 12) msg = 'Good afternoon!'; + else if (now >= 6) msg = 'Good morning!'; + else if (now >= 0) msg = 'Good night!'; + else msg = 'Hello!'; + + return msg; +} \ No newline at end of file diff --git a/client/src/components/UI/Modal/Modal.tsx b/client/src/components/UI/Modal/Modal.tsx index b8b86eb..ccb82be 100644 --- a/client/src/components/UI/Modal/Modal.tsx +++ b/client/src/components/UI/Modal/Modal.tsx @@ -1,4 +1,4 @@ -import { MouseEvent, useRef, useEffect } from 'react'; +import { MouseEvent, useRef } from 'react'; import classes from './Modal.module.css'; diff --git a/client/src/store/actions/app.ts b/client/src/store/actions/app.ts index 1699e31..a651cd2 100644 --- a/client/src/store/actions/app.ts +++ b/client/src/store/actions/app.ts @@ -89,7 +89,7 @@ export interface DeleteAppAction { export const deleteApp = (id: number) => async (dispatch: Dispatch) => { try { - const res = await axios.delete>(`/api/apps/${id}`); + await axios.delete>(`/api/apps/${id}`); dispatch({ type: ActionTypes.createNotification, diff --git a/client/src/store/actions/bookmark.ts b/client/src/store/actions/bookmark.ts index 11a8909..9608ebc 100644 --- a/client/src/store/actions/bookmark.ts +++ b/client/src/store/actions/bookmark.ts @@ -130,7 +130,7 @@ export interface DeleteCategoryAction { export const deleteCategory = (id: number) => async (dispatch: Dispatch) => { try { - const res = await axios.delete>(`/api/categories/${id}`); + await axios.delete>(`/api/categories/${id}`); dispatch({ type: ActionTypes.createNotification, @@ -191,7 +191,7 @@ export interface DeleteBookmarkAction { export const deleteBookmark = (bookmarkId: number, categoryId: number) => async (dispatch: Dispatch) => { try { - const res = await axios.delete>(`/api/bookmarks/${bookmarkId}`); + await axios.delete>(`/api/bookmarks/${bookmarkId}`); dispatch({ type: ActionTypes.createNotification,