This commit is contained in:
Bever1337 2020-05-20 15:28:14 -04:00
parent 4f6f479134
commit 3a337e6408
20 changed files with 631 additions and 358 deletions

View file

@ -1,11 +1,9 @@
import React from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import MaterialIcon from 'material-icons-react';
import styled from 'styled-components';
import appData from './data/apps.json';
import themeData from './data/themes.json'
const selectedTheme = localStorage.getItem("theme") ? JSON.parse(localStorage.getItem("theme")) : themeData.themes[0];
import { Button } from './button';
import { selectedTheme } from '../selectedTheme';
const AppListContainer = styled.div`
padding: 2rem 0 2rem 0;
@ -69,25 +67,69 @@ const Description = styled.p`
color: ${selectedTheme.accentColor};
`;
const appList = () => (
<AppListContainer>
<ApplicationsText>Applications</ApplicationsText>
<AppsContainer>
{
appData.apps.map((app) => (
<AppContainer>
<IconContainer>
<MaterialIcon icon={app.icon} color={selectedTheme.mainColor}/>
</IconContainer>
<AppDetails>
<Link href={app.URL}>{app.name}</Link>
<Description>{app.displayURL}</Description>
</AppDetails>
</AppContainer>
))
}
</AppsContainer>
</AppListContainer>
);
const ErrorMessage = styled.p`
color: red;
`;
export default appList;
function handleResponse(response) {
if (response.ok) {
return response.json();
}
throw new Error('Failed to load app data.');
}
function useAppData() {
const [appData, setAppData] = useState({ apps: [], error: false });
const fetchAppData = useCallback(() => {
(process.env.NODE_ENV === 'production'
? fetch('/apps.json').then(handleResponse)
: import('./data/apps.json')
)
.then((jsonResponse) => {
setAppData({ ...jsonResponse, error: false });
})
.catch((error) => {
setAppData({ apps: [], error: error.message });
});
}, []);
useEffect(() => {
fetchAppData();
}, [fetchAppData]);
return { appData, fetchAppData };
}
const AppList = () => {
const {
appData: { apps, error },
fetchAppData,
} = useAppData();
return (
<AppListContainer>
<ApplicationsText>
Applications <Button onClick={fetchAppData}>refresh</Button>
</ApplicationsText>
<AppsContainer>
{error && <ErrorMessage>{error}</ErrorMessage>}
{apps.map((app, idx) => {
const { name } = app;
return (
<AppContainer key={[name, idx].join('')}>
<IconContainer>
<MaterialIcon
icon={app.icon}
color={selectedTheme.mainColor}
/>
</IconContainer>
<AppDetails>
<Link href={app.URL}>{app.name}</Link>
<Description>{app.displayURL}</Description>
</AppDetails>
</AppContainer>
);
})}
</AppsContainer>
</AppListContainer>
);
};
export default AppList;

View file

@ -3,8 +3,7 @@ import styled from 'styled-components';
import bookmarkData from './data/bookmarks.json';
import themeData from './data/themes.json'
const selectedTheme = localStorage.getItem("theme") ? JSON.parse(localStorage.getItem("theme")) : themeData.themes[0];
import { selectedTheme } from '../selectedTheme';
const BookmarksText = styled.h3`
font-family: Roboto, sans-serif;
@ -54,26 +53,24 @@ const Bookmark = styled.a`
font-size: 14px;
`;
const bookmarkList = () => (
const BookmarkList = () => (
<BookmarkListContainer>
<BookmarksText>Bookmarks</BookmarksText>
<BookmarksContainer>
{
bookmarkData.groups.map((group) => (
<BookmarkGroupContainer>
<GroupText>{group.name}</GroupText>
{
group.items.map((link) => (
<Bookmark href={link.url}>{link.name}</Bookmark>
))
}
</BookmarkGroupContainer>
))
}
{bookmarkData.groups.map(({ name, items }) => {
return (
<BookmarkGroupContainer key={name}>
<GroupText>{name}</GroupText>
{items.map(({ url, name: linkName }) => (
<Bookmark key={linkName} href={url}>
{linkName}
</Bookmark>
))}
</BookmarkGroupContainer>
);
})}
</BookmarksContainer>
</BookmarkListContainer>
);
export default bookmarkList;
export default BookmarkList;

13
src/components/button.js Normal file
View file

@ -0,0 +1,13 @@
import styled from 'styled-components';
import { selectedTheme } from '../selectedTheme';
export const Button = styled.button`
font-family: Roboto, sans-serif;
text-transform: uppercase;
font-weight: 400;
border: 1px solid ${selectedTheme.mainColor};
color: ${selectedTheme.mainColor};
background: none;
margin-left: 1rem;
min-height: 3em;
`;

View file

@ -55,4 +55,4 @@
"icon": "show_chart"
}
]
}
}

View file

@ -137,4 +137,4 @@
]
}
]
}
}

View file

@ -1,64 +1,64 @@
{
"providers":[
{
"name":"Allmusic",
"url":"https://www.allmusic.com/search/all/",
"prefix":"/a"
},
{
"name":"Discogs",
"url":"https://www.discogs.com/search/?q=",
"prefix":"/di"
},
{
"name":"Duck Duck Go",
"url":"https://duckduckgo.com/?q=",
"prefix":"/d"
},
{
"name":"iMDB",
"url":"https://www.imdb.com/find?q=",
"prefix":"/i"
},
{
"name":"TheMovieDB",
"url":"https://www.themoviedb.org/search?query=",
"prefix":"/m"
},
{
"name":"Reddit",
"url":"https://www.reddit.com/search?q=",
"prefix":"/r"
},
{
"name":"Qwant",
"url":"https://www.qwant.com/?q=",
"prefix":"/q"
},
{
"name":"Soundcloud",
"url":"https://soundcloud.com/search?q=",
"prefix":"/so"
},
{
"name":"Spotify",
"url":"https://open.spotify.com/search/results/",
"prefix":"/s"
},
{
"name":"TheTVDB",
"url":"https://www.thetvdb.com/search?q=",
"prefix":"/tv"
},
{
"name":"Trakt",
"url":"https://trakt.tv/search?query=",
"prefix":"/t"
},
{
"name": "YouTube",
"url": "https://youtube.com/results?search_query=",
"prefix":"/yt"
}
"providers": [
{
"name": "Allmusic",
"url": "https://www.allmusic.com/search/all/",
"prefix": "/a"
},
{
"name": "Discogs",
"url": "https://www.discogs.com/search/?q=",
"prefix": "/di"
},
{
"name": "Duck Duck Go",
"url": "https://duckduckgo.com/?q=",
"prefix": "/d"
},
{
"name": "iMDB",
"url": "https://www.imdb.com/find?q=",
"prefix": "/i"
},
{
"name": "TheMovieDB",
"url": "https://www.themoviedb.org/search?query=",
"prefix": "/m"
},
{
"name": "Reddit",
"url": "https://www.reddit.com/search?q=",
"prefix": "/r"
},
{
"name": "Qwant",
"url": "https://www.qwant.com/?q=",
"prefix": "/q"
},
{
"name": "Soundcloud",
"url": "https://soundcloud.com/search?q=",
"prefix": "/so"
},
{
"name": "Spotify",
"url": "https://open.spotify.com/search/results/",
"prefix": "/s"
},
{
"name": "TheTVDB",
"url": "https://www.thetvdb.com/search?q=",
"prefix": "/tv"
},
{
"name": "Trakt",
"url": "https://trakt.tv/search?query=",
"prefix": "/t"
},
{
"name": "YouTube",
"url": "https://youtube.com/results?search_query=",
"prefix": "/yt"
}
]
}
}

View file

@ -22,4 +22,4 @@
"backgroundColor": "#ffffff"
}
]
}
}

View file

@ -1,8 +1,7 @@
import React from 'react';
import styled from 'styled-components';
import themeData from './data/themes.json'
const selectedTheme = localStorage.getItem("theme") ? JSON.parse(localStorage.getItem("theme")) : themeData.themes[0];
import { selectedTheme } from '../selectedTheme';
const GreeterContainer = styled.div`
padding: 2rem 0 2rem 0;
@ -27,47 +26,75 @@ const DateText = styled.h3`
const getGreeting = () => {
// Maybe add some expandability for different greetings?
return "Hello World!"
}
return 'Hello World!';
};
const getExtension = (day) => {
let extension = ""
let extension = '';
if ((day > 4 && day <= 20) || (day > 20 && day % 10 >= 4)) {
extension = "th"
extension = 'th';
} else if (day % 10 === 1) {
extension = "st"
extension = 'st';
} else if (day % 10 === 2) {
extension = "nd"
extension = 'nd';
} else if (day % 10 === 3) {
extension = "rd"
extension = 'rd';
}
return extension
}
return extension;
};
const monthNames = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];
const weekDayNames = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
];
const getDateString = () => {
let currentDate = new Date();
const monthNames = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
const weekDayNames = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ];
return weekDayNames[currentDate.getUTCDay()] + ", " + monthNames[currentDate.getUTCMonth()] + " " + currentDate.getDate() + getExtension(currentDate.getDate()) + " " + currentDate.getFullYear();
}
const greeter = () => {
return (
weekDayNames[currentDate.getUTCDay()] +
', ' +
monthNames[currentDate.getUTCMonth()] +
' ' +
currentDate.getDate() +
getExtension(currentDate.getDate()) +
' ' +
currentDate.getFullYear()
);
};
const Greeter = () => {
let date = getDateString();
let greeting = getGreeting();
return (
<GreeterContainer>
<DateText>{ date }</DateText>
<GreetText>{ greeting }</GreetText>
<DateText>{date}</DateText>
<GreetText>{greeting}</GreetText>
</GreeterContainer>
);
}
};
export default greeter;
export default Greeter;

View file

@ -1,10 +1,9 @@
import React, {useState} from 'react';
import React, { useState } from 'react';
import styled from 'styled-components';
import searchData from './data/search.json';
import themeData from './data/themes.json';
const selectedTheme = localStorage.getItem("theme") ? JSON.parse(localStorage.getItem("theme")) : themeData.themes[0];
import { selectedTheme } from '../selectedTheme';
const SearchInput = styled.input`
width: 100%;
@ -17,53 +16,53 @@ const SearchInput = styled.input`
`;
const handleQueryWithProvider = (query) => {
let queryArray = query.split(" ");
let queryArray = query.split(' ');
let prefix = queryArray[0];
queryArray.shift();
let searchQuery = queryArray.join(" ");
let searchQuery = queryArray.join(' ');
var foundProvider = false;
searchData.providers.forEach((provider) => {
if (provider.prefix === prefix) {
foundProvider = true;
window.location = provider.url + searchQuery
window.location = provider.url + searchQuery;
}
})
});
if (!foundProvider) {
window.location = "https://google.com/search?q=" + query;
window.location = 'https://google.com/search?q=' + query;
}
}
};
const SearchBar = () => {
let [input, setInput] = useState();
const handleSearchQuery = (e) => {
var query = input;
console.log(query)
console.log(query);
if (query.split(" ")[0].includes("/")) {
handleQueryWithProvider(query)
if (query.split(' ')[0].includes('/')) {
handleQueryWithProvider(query);
} else {
window.location = "https://google.com/search?q=" + query;
window.location = 'https://google.com/search?q=' + query;
}
e.preventDefault();
}
};
return (
<form onSubmit={(e) => handleSearchQuery(e)}>
<SearchInput type="text" onChange={(e) => setInput(e.target.value)}></SearchInput>
<SearchInput
type="text"
onChange={(e) => setInput(e.target.value)}
></SearchInput>
<button type="submit" hidden />
</form>
)
}
);
};
export default SearchBar;
export default SearchBar;

View file

@ -4,10 +4,11 @@ import styled from 'styled-components';
import Select from 'react-select';
import searchData from './data/search.json'
import themeData from './data/themes.json'
import searchData from './data/search.json';
import themeData from './data/themes.json';
import getTheme, { setTheme } from './themeManager'
import getTheme, { setTheme } from './themeManager';
import { Button } from './button';
const selectedTheme = getTheme();
@ -47,15 +48,7 @@ const FormContainer = styled.div`
flex-wrap: nowrap;
`;
const ApplyButton = styled.button`
font-family: Roboto, sans-serif;
text-transform: uppercase;
font-weight: 400;
border: 1px solid ${selectedTheme.mainColor};
color: ${selectedTheme.mainColor};
background: none;
margin-left: 1rem;
`;
const ApplyButton = Button;
const Headline = styled.h3`
font-family: Roboto, sans-serif;
@ -67,48 +60,47 @@ const Headline = styled.h3`
const SelectorStyle = {
control: (provided) => ({
...provided,
fontFamily: "Roboto, sans-serif",
fontWeight: "500",
fontFamily: 'Roboto, sans-serif',
fontWeight: '500',
color: selectedTheme.mainColor,
textTransform: "uppercase",
width: "200px",
background: "none",
borderRadius: "0px",
border: "1px solid " + selectedTheme.mainColor,
textTransform: 'uppercase',
width: '200px',
background: 'none',
borderRadius: '0px',
border: '1px solid ' + selectedTheme.mainColor,
boxShadow: 0,
'&:hover': {
border: "1px solid " + selectedTheme.mainColor,
}
border: '1px solid ' + selectedTheme.mainColor,
},
}),
menu: (provided) => ({
...provided,
backgroundColor: selectedTheme.backgroundColor,
border: "1px solid " + selectedTheme.mainColor,
borderRadius: "0px",
border: '1px solid ' + selectedTheme.mainColor,
borderRadius: '0px',
boxShadow: 0,
}),
option: (provided) => ({
...provided,
fontFamily: "Roboto, sans-serif",
fontWeight: "500",
fontFamily: 'Roboto, sans-serif',
fontWeight: '500',
color: selectedTheme.mainColor,
textTransform: "uppercase",
borderRadius: "0px",
textTransform: 'uppercase',
borderRadius: '0px',
boxShadow: 0,
backgroundColor: selectedTheme.backgroundColor,
'&:hover': {
backgroundColor: selectedTheme.mainColor,
color: selectedTheme.backgroundColor,
}
},
}),
singleValue: (provided) => {
return {
...provided,
color: selectedTheme.mainColor,
}
}
}
};
},
};
const Table = styled.table`
font-family: Roboto, sans-serif;
@ -132,7 +124,6 @@ const HeadCell = styled.th`
`;
const SettingsModal = () => {
const [modalHidden, setModalHidden] = useState(true);
const [newTheme, setNewTheme] = useState();
@ -143,33 +134,49 @@ const SettingsModal = () => {
</ModalButton>
<Modal hidden={modalHidden}>
<ExitButton onClick={() => setModalHidden(!modalHidden)}>
<MaterialIcon icon="close" color={selectedTheme.mainColor} />
<MaterialIcon
icon="close"
color={selectedTheme.mainColor}
/>
</ExitButton>
<SelectContainer>
<Headline>Theme:</Headline>
<FormContainer>
<Select options={themeData.themes} defaultValue={selectedTheme} onChange={(e) => {setNewTheme(e)}} styles={SelectorStyle} />
<ApplyButton onClick={() => setTheme(JSON.stringify(newTheme))}>Apply</ApplyButton>
<Select
options={themeData.themes}
defaultValue={selectedTheme}
onChange={(e) => {
setNewTheme(e);
}}
styles={SelectorStyle}
/>
<ApplyButton
onClick={() => setTheme(JSON.stringify(newTheme))}
>
Apply
</ApplyButton>
</FormContainer>
</SelectContainer>
<Table>
<TableRow>
<HeadCell>Search Provider</HeadCell>
<HeadCell>Prefix</HeadCell>
</TableRow>
{
searchData.providers.map((provider) => (
<TableRow>
<TableCell>{provider.name}</TableCell>
<TableCell>{provider.prefix}</TableCell>
</TableRow>
))
}
<tbody>
<TableRow>
<HeadCell>Search Provider</HeadCell>
<HeadCell>Prefix</HeadCell>
</TableRow>
{searchData.providers.map((provider) => {
const { name, prefix } = provider;
return (
<TableRow key={name}>
<TableCell>{name}</TableCell>
<TableCell>{prefix}</TableCell>
</TableRow>
);
})}
</tbody>
</Table>
</Modal>
</>
)
);
};
}
export default SettingsModal;
export default SettingsModal;

View file

@ -1,25 +1,27 @@
import themeData from './data/themes.json';
const setTheme = (theme) => {
localStorage.setItem("theme", theme);
localStorage.setItem('theme', theme);
window.location.reload();
}
};
const resetTheme = () => {
localStorage.removeItem("theme");
}
localStorage.removeItem('theme');
};
const getTheme = () => {
let selectedTheme = themeData.themes[0];
if (localStorage.getItem("theme") && localStorage.getItem("theme") !== undefined) {
selectedTheme = JSON.parse(localStorage.getItem("theme"));
if (
localStorage.getItem('theme') &&
localStorage.getItem('theme') !== undefined
) {
selectedTheme = JSON.parse(localStorage.getItem('theme'));
}
return selectedTheme;
}
};
export { setTheme, resetTheme }
export { setTheme, resetTheme };
export default getTheme;
export default getTheme;