From 746505294bcab1dc4341378496e429285d4d938c Mon Sep 17 00:00:00 2001 From: phntxx Date: Sat, 3 Apr 2021 16:54:44 +0200 Subject: [PATCH] Feature Requests --- data/greeter.json | 50 ++++++++++++++++++ package.json | 12 +++++ src/app.tsx | 6 +-- src/components/app.tsx | 35 +++++++----- src/components/appCategory.tsx | 1 + src/components/appList.tsx | 1 - src/components/greeter.tsx | 97 ++++++++++++++++------------------ src/components/settings.tsx | 45 ++++++---------- src/data/greeter.json | 50 ++++++++++++++++++ src/lib/fetcher.tsx | 77 ++++++++++++++++++++++++--- tsconfig.json | 2 +- 11 files changed, 272 insertions(+), 104 deletions(-) create mode 100644 data/greeter.json create mode 100644 src/data/greeter.json diff --git a/data/greeter.json b/data/greeter.json new file mode 100644 index 0000000..487bd37 --- /dev/null +++ b/data/greeter.json @@ -0,0 +1,50 @@ +{ + "greeter": { + "months": [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + ], + "days": [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" + ], + "greetings": [ + { + "greeting": "Good night!", + "start": 0, + "end": 6 + }, + { + "greeting": "Good morning!", + "start": 6, + "end": 12 + }, + { + "greeting": "Good afternoon!", + "start": 12, + "end": 18 + }, + { + "greeting": "Good evening!", + "start": 18, + "end": 0 + } + ], + "dateformat": "%wd, %m %d%e %y" + } +} diff --git a/package.json b/package.json index f72d980..d230260 100644 --- a/package.json +++ b/package.json @@ -30,5 +30,17 @@ }, "eslintConfig": { "extends": "react-app" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] } } diff --git a/src/app.tsx b/src/app.tsx index 96c9ec8..0245f9e 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,4 +1,3 @@ -import React from "react"; import { createGlobalStyle } from "styled-components"; import SearchBar from "./components/searchBar"; @@ -31,7 +30,7 @@ const GlobalStyle = createGlobalStyle` */ const App = () => { - const { appData, bookmarkData, searchProviderData, themeData, imprintData } = useFetcher(); + const { appData, bookmarkData, searchProviderData, themeData, imprintData, greeterData } = useFetcher(); return ( <> @@ -44,8 +43,7 @@ const App = () => { providers={searchProviderData?.providers} /> )} - - + {!appData.error && ( )} diff --git a/src/components/app.tsx b/src/components/app.tsx index 8987287..aabd910 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect } from "react"; import Icon from "./icon"; import styled from "styled-components"; import selectedTheme from "../lib/theme"; @@ -48,20 +48,31 @@ export interface IAppProps { icon: string; url: string; displayURL: string; + newTab?: boolean; } /** * Renders a single app shortcut * @param {IAppProps} props - The props of the given app */ -export const App = ({ name, icon, url, displayURL }: IAppProps) => ( - - - - - - {name} - {displayURL} - - -); +export const App = ({ name, icon, url, displayURL, newTab }: IAppProps) => { + + useEffect(() => { console.log(newTab) }, [newTab]) + + return ( + + + + + + + { + (newTab !== undefined && newTab) ? + {name} : {name} + } + + {displayURL} + + + ); +} diff --git a/src/components/appCategory.tsx b/src/components/appCategory.tsx index c13aacd..83d0fc3 100644 --- a/src/components/appCategory.tsx +++ b/src/components/appCategory.tsx @@ -31,6 +31,7 @@ export const AppCategory = ({ name, items }: IAppCategoryProps) => ( icon={app.icon} url={app.url} displayURL={app.displayURL} + newTab={app.newTab} /> ))} diff --git a/src/components/appList.tsx b/src/components/appList.tsx index b09529c..3781438 100644 --- a/src/components/appList.tsx +++ b/src/components/appList.tsx @@ -1,4 +1,3 @@ -import React from "react"; import { AppCategory, IAppCategoryProps } from "./appCategory"; import { IAppProps } from "./app"; diff --git a/src/components/greeter.tsx b/src/components/greeter.tsx index 14bb96a..b91185d 100644 --- a/src/components/greeter.tsx +++ b/src/components/greeter.tsx @@ -1,6 +1,4 @@ -import React from "react"; import styled from "styled-components"; - import selectedTheme from "../lib/theme"; const GreeterContainer = styled.div` @@ -22,48 +20,45 @@ const DateText = styled.h3` color: ${selectedTheme.accentColor}; `; -const monthNames = [ - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", -]; +export interface IGreeterProps { + months: Array; + days: Array; + greetings: Array; + dateformat: string; +} -const weekDayNames = [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", -]; +interface IGreetingProps { + greeting: string; + start: number; + end: number; +} + +interface IGreeterComponentProps { + data: IGreeterProps; +} + +/** + * + * @param a the number that's supposed to be checked + * @param b the minimum + * @param c the maximum + */ +const isBetween = (a: number, b: number, c: number): boolean => (a > b && a < c) /** * Returns a greeting based on the current time * @returns {string} - A greeting */ -const getGreeting = () => { - switch (Math.floor(new Date().getHours() / 6)) { - case 0: - return "Good night!"; - case 1: - return "Good morning!"; - case 2: - return "Good afternoon!"; - case 3: - return "Good evening!"; - default: - break; - } +const getGreeting = (greetings: Array): string => { + + let hours = Math.floor(new Date().getHours()) + let result = ""; + + greetings.forEach(greeting => { + if (isBetween(hours, greeting.start, greeting.end)) result = greeting.greeting; + }) + + return result; }; /** @@ -89,30 +84,28 @@ const getExtension = (day: number) => { /** * Generates the current date + * @param {string} format - The format of the date string * @returns {string} - The current date as a string */ -const getDateString = () => { +const getDateString = (weekdays: Array, months: Array, format: string) => { let currentDate = new Date(); - return ( - weekDayNames[currentDate.getUTCDay()] + - ", " + - monthNames[currentDate.getUTCMonth()] + - " " + - currentDate.getDate() + - getExtension(currentDate.getDate()) + - " " + - currentDate.getFullYear() - ); + let weekday = weekdays[currentDate.getUTCDay()]; + let day = currentDate.getDate(); + let month = months[currentDate.getUTCMonth()]; + let extension = getExtension(day); + let year = currentDate.getFullYear(); + + return format.replace("%wd", weekday).replace("%d", day.toString()).replace("%e", extension).replace("%m", month).replace("%y", year.toString()); }; /** * Renders the Greeter */ -const Greeter = () => ( +const Greeter = ({ data }: IGreeterComponentProps) => ( - {getDateString()} - {getGreeting()} + {getDateString(data.days, data.months, data.dateformat)} + {getGreeting(data.greetings)} ); diff --git a/src/components/settings.tsx b/src/components/settings.tsx index a765697..3e69737 100644 --- a/src/components/settings.tsx +++ b/src/components/settings.tsx @@ -1,7 +1,7 @@ import React, { useState } from "react"; import styled from "styled-components"; -import Select, { Styles, ValueType } from "react-select"; +import Select, { ValueType } from "react-select"; import { ISearchProviderProps } from "./searchBar"; import selectedTheme, { setTheme, IThemeProps } from "../lib/theme"; @@ -9,17 +9,6 @@ import { Button, SubHeadline } from "./elements"; import Modal from "./modal"; -interface IHoverProps { - color?: string; - backgroundColor?: string; - border?: string; - borderColor?: string; -} - -interface IPseudoProps extends React.CSSProperties { - "&:hover": IHoverProps -} - const FormContainer = styled.div` display: grid; grid-template-columns: auto auto auto; @@ -55,22 +44,12 @@ const SectionHeadline = styled(SubHeadline)` margin-bottom: 0.5rem; `; -const SelectorStyle: Partial> = { - indicatorSeparator: () => ({ - display: "none", - }), - container: (base: React.CSSProperties): React.CSSProperties => ({ +const SelectorStyle: any = { + container: (base: any): any => ({ ...base, margin: "0 2px", }), - dropdownIndicator: (base: React.CSSProperties): IPseudoProps => ({ - ...base, - color: selectedTheme.mainColor, - "&:hover": { - color: selectedTheme.mainColor - } - }), - control: (base: React.CSSProperties): IPseudoProps => ({ + control: (base: any): any => ({ ...base, fontWeight: 500, color: selectedTheme.mainColor, @@ -86,7 +65,17 @@ const SelectorStyle: Partial> = { borderColor: selectedTheme.mainColor }, }), - menu: (base: React.CSSProperties): React.CSSProperties => ({ + dropdownIndicator: (base: any): any => ({ + ...base, + color: selectedTheme.mainColor, + "&:hover": { + color: selectedTheme.mainColor + } + }), + indicatorSeparator: () => ({ + display: "none", + }), + menu: (base: any): any => ({ ...base, backgroundColor: selectedTheme.backgroundColor, border: "1px solid " + selectedTheme.mainColor, @@ -94,7 +83,7 @@ const SelectorStyle: Partial> = { boxShadow: "none", margin: "4px 0" }), - option: (base: React.CSSProperties): IPseudoProps => ({ + option: (base: any): any => ({ ...base, fontWeight: 500, color: selectedTheme.mainColor, @@ -107,7 +96,7 @@ const SelectorStyle: Partial> = { color: selectedTheme.backgroundColor, }, }), - singleValue: (base: React.CSSProperties): React.CSSProperties => ({ + singleValue: (base: any): any => ({ ...base, color: selectedTheme.mainColor, }), diff --git a/src/data/greeter.json b/src/data/greeter.json new file mode 100644 index 0000000..487bd37 --- /dev/null +++ b/src/data/greeter.json @@ -0,0 +1,50 @@ +{ + "greeter": { + "months": [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + ], + "days": [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" + ], + "greetings": [ + { + "greeting": "Good night!", + "start": 0, + "end": 6 + }, + { + "greeting": "Good morning!", + "start": 6, + "end": 12 + }, + { + "greeting": "Good afternoon!", + "start": 12, + "end": 18 + }, + { + "greeting": "Good evening!", + "start": 18, + "end": 0 + } + ], + "dateformat": "%wd, %m %d%e %y" + } +} diff --git a/src/lib/fetcher.tsx b/src/lib/fetcher.tsx index 54a362b..2aa6aaa 100644 --- a/src/lib/fetcher.tsx +++ b/src/lib/fetcher.tsx @@ -6,6 +6,7 @@ import { IAppCategoryProps } from "../components/appCategory"; import { IAppProps } from "../components/app"; import { IThemeProps } from "./theme"; import { IImprintProps } from "../components/imprint"; +import { IGreeterProps } from "../components/greeter"; const errorMessage = "Failed to load data."; const inProduction = process.env.NODE_ENV === "production"; @@ -47,6 +48,11 @@ export interface IImprintDataProps { error: string | boolean; } +export interface IGreeterDataProps { + greeter: IGreeterProps; + error: string | boolean; +} + /** * Default values for the respective state variables */ @@ -79,6 +85,57 @@ const defaults = { }, error: false, }, + greeter: { + greeter: { + months: [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + ], + days: [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" + ], + greetings: [ + { + greeting: "Good night!", + start: 0, + end: 6 + }, + { + greeting: "Good morning!", + start: 6, + end: 12 + }, + { + greeting: "Good afternoon!", + start: 12, + end: 18 + }, + { + greeting: "Good evening!", + start: 18, + end: 0 + } + ], + dateformat: "%wd, %m %d%e %y" + }, + error: false, + } }; /** @@ -98,6 +155,8 @@ const handleError = (status: string, error: Error) => { return { ...defaults.theme, error: error.message } case "imprint": return { ...defaults.imprint, error: error.message } + case "greeter": + return { ...defaults.greeter, error: error.message } default: break; } @@ -112,6 +171,7 @@ const fetchProduction = Promise.all([ fetch("/data/search.json").then(handleResponse).catch((error: Error) => handleError("searchProvider", error)), fetch("/data/themes.json").then(handleResponse).catch((error: Error) => handleError("theme", error)), fetch("/data/imprint.json").then(handleResponse).catch((error: Error) => handleError("imprint", error)), + fetch("/data/greeter.json").then(handleResponse).catch((error: Error) => handleError("greeter", error)) ]); /** @@ -123,6 +183,7 @@ const fetchDevelopment = Promise.all([ import("../data/search.json"), import("../data/themes.json"), import("../data/imprint.json"), + import("../data/greeter.json") ]); /** @@ -146,14 +207,17 @@ export const useFetcher = () => { defaults.imprint ); + const [greeterData, setGreeterData] = useState(defaults.greeter); + const callback = useCallback(() => { (inProduction ? fetchProduction : fetchDevelopment).then( - ([appData, bookmarkData, searchData, themeData, imprintData]: [IAppDataProps, IBookmarkDataProps, ISearchProviderDataProps, IThemeDataProps, IImprintDataProps]) => { - (appData.error) ? setAppData(appData) : setAppData({ ...appData, error: false }); - (bookmarkData.error) ? setBookmarkData(bookmarkData) : setBookmarkData({ ...bookmarkData, error: false }); - (searchData.error) ? setSearchProviderData(searchData) : setSearchProviderData({ ...searchData, error: false }); - (themeData.error) ? setThemeData(themeData) : setThemeData({ ...themeData, error: false }); - (imprintData.error) ? setImprintData(imprintData) : setImprintData({ ...imprintData, error: false }); + ([appData, bookmarkData, searchData, themeData, imprintData, greeterData]: [IAppDataProps, IBookmarkDataProps, ISearchProviderDataProps, IThemeDataProps, IImprintDataProps, IGreeterDataProps]) => { + setAppData((appData.error) ? appData : { ...appData, error: false }); + setBookmarkData((bookmarkData.error) ? bookmarkData : { ...bookmarkData, error: false }); + setSearchProviderData((searchData.error) ? searchData : { ...searchData, error: false }); + setThemeData((themeData.error) ? themeData : { ...themeData, error: false }); + setImprintData((imprintData.error) ? imprintData : { ...imprintData, error: false }); + setGreeterData((greeterData.error) ? greeterData : { ...greeterData, error: false }); } ); }, []); @@ -166,6 +230,7 @@ export const useFetcher = () => { searchProviderData, themeData, imprintData, + greeterData, callback }; }; diff --git a/tsconfig.json b/tsconfig.json index fbce9be..e18c413 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,7 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "react", + "jsx": "react-jsx", "noFallthroughCasesInSwitch": true }, "include": [