Added support for categories
This commit is contained in:
parent
d2b35f7339
commit
9c372553f9
6 changed files with 106 additions and 63 deletions
|
@ -12,6 +12,7 @@ import selectedTheme from './components/themeManager';
|
|||
const GlobalStyle = createGlobalStyle`
|
||||
body {
|
||||
background-color: ${selectedTheme.backgroundColor};
|
||||
font-family: Roboto, sans-serif;
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
|
@ -7,10 +7,11 @@ import selectedTheme from './themeManager';
|
|||
import {
|
||||
handleResponse,
|
||||
Headline,
|
||||
SubHeadline,
|
||||
ListContainer,
|
||||
ItemList,
|
||||
Item,
|
||||
ErrorMessage
|
||||
ErrorMessage,
|
||||
} from './elements';
|
||||
|
||||
const IconContainer = styled.div`
|
||||
|
@ -46,9 +47,13 @@ const Description = styled.p`
|
|||
color: ${selectedTheme.accentColor};
|
||||
`;
|
||||
|
||||
const CategoryContainer = styled.div`
|
||||
padding: 1rem 0;
|
||||
`;
|
||||
|
||||
const App = styled.div`
|
||||
display: flex;
|
||||
flex-basis: 25%;
|
||||
flex: auto 25%;
|
||||
padding: 1rem;
|
||||
`;
|
||||
|
||||
|
@ -59,11 +64,11 @@ const useAppData = () => {
|
|||
? fetch('/data/apps.json').then(handleResponse)
|
||||
: import('./data/apps.json')
|
||||
)
|
||||
.then(jsonResponse => {
|
||||
.then((jsonResponse) => {
|
||||
setAppData({ ...jsonResponse, error: false });
|
||||
})
|
||||
.catch(error => {
|
||||
setAppData({ apps: [], error: error.message });
|
||||
.catch((error) => {
|
||||
setAppData({ categories: [], apps: [], error: error.message });
|
||||
});
|
||||
}, []);
|
||||
|
||||
|
@ -75,32 +80,66 @@ const useAppData = () => {
|
|||
|
||||
const AppList = () => {
|
||||
const {
|
||||
appData: { apps, error }
|
||||
appData: { categories, apps, error },
|
||||
} = useAppData();
|
||||
return (
|
||||
<ListContainer>
|
||||
<Headline>Applications</Headline>
|
||||
|
||||
{categories && (
|
||||
<CategoryContainer>
|
||||
{categories.map((category, idx) => (
|
||||
<>
|
||||
<SubHeadline key={[category.name, idx].join('')}>
|
||||
{category.name}
|
||||
</SubHeadline>
|
||||
<ItemList>
|
||||
{category.items.map((app, idx) => (
|
||||
<Item key={[app.name, idx].join('')}>
|
||||
<App>
|
||||
<IconContainer>
|
||||
<MaterialIcon
|
||||
icon={app.icon}
|
||||
color={
|
||||
selectedTheme.mainColor
|
||||
}
|
||||
/>
|
||||
</IconContainer>
|
||||
<DetailsContainer>
|
||||
<Link href={app.URL}>
|
||||
{app.name}
|
||||
</Link>
|
||||
<Description>
|
||||
{app.displayURL}
|
||||
</Description>
|
||||
</DetailsContainer>
|
||||
</App>
|
||||
</Item>
|
||||
))}
|
||||
</ItemList>
|
||||
</>
|
||||
))}
|
||||
</CategoryContainer>
|
||||
)}
|
||||
|
||||
<ItemList>
|
||||
{error && <ErrorMessage>{error}</ErrorMessage>}
|
||||
{apps.map((app, idx) => {
|
||||
const { name } = app;
|
||||
return (
|
||||
<Item key={[name, idx].join('')}>
|
||||
<App>
|
||||
<IconContainer>
|
||||
<MaterialIcon
|
||||
icon={app.icon}
|
||||
color={selectedTheme.mainColor}
|
||||
/>
|
||||
</IconContainer>
|
||||
<DetailsContainer>
|
||||
<Link href={app.URL}>{app.name}</Link>
|
||||
<Description>{app.displayURL}</Description>
|
||||
</DetailsContainer>
|
||||
</App>
|
||||
</Item>
|
||||
);
|
||||
})}
|
||||
{apps.map((app, idx) => (
|
||||
<Item key={[app.name, idx].join('')}>
|
||||
<App>
|
||||
<IconContainer>
|
||||
<MaterialIcon
|
||||
icon={app.icon}
|
||||
color={selectedTheme.mainColor}
|
||||
/>
|
||||
</IconContainer>
|
||||
<DetailsContainer>
|
||||
<Link href={app.URL}>{app.name}</Link>
|
||||
<Description>{app.displayURL}</Description>
|
||||
</DetailsContainer>
|
||||
</App>
|
||||
</Item>
|
||||
))}
|
||||
</ItemList>
|
||||
</ListContainer>
|
||||
);
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
ListContainer,
|
||||
ItemList,
|
||||
Item,
|
||||
ErrorMessage
|
||||
ErrorMessage,
|
||||
} from './elements';
|
||||
|
||||
const Group = styled.h4`
|
||||
|
@ -23,7 +23,7 @@ const BookmarkGroup = styled.div`
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 2 1 auto;
|
||||
padding: 1rem 0 1rem 0;
|
||||
padding: 1rem 0;
|
||||
`;
|
||||
|
||||
const Bookmark = styled.a`
|
||||
|
@ -31,7 +31,7 @@ const Bookmark = styled.a`
|
|||
font-weight: 400;
|
||||
text-decoration: none;
|
||||
color: ${selectedTheme.accentColor};
|
||||
padding: 10px 0 0 0;
|
||||
padding-top: 10px;
|
||||
font-size: 14px;
|
||||
|
||||
&:hover {
|
||||
|
@ -42,7 +42,7 @@ const Bookmark = styled.a`
|
|||
const useBookmarkData = () => {
|
||||
const [bookmarkData, setBookmarkData] = useState({
|
||||
groups: [],
|
||||
error: false
|
||||
error: false,
|
||||
});
|
||||
|
||||
const fetchBookmarkData = useCallback(() => {
|
||||
|
@ -50,10 +50,10 @@ const useBookmarkData = () => {
|
|||
? fetch('/data/bookmarks.json').then(handleResponse)
|
||||
: import('./data/bookmarks.json')
|
||||
)
|
||||
.then(jsonResponse => {
|
||||
.then((jsonResponse) => {
|
||||
setBookmarkData({ ...jsonResponse, error: false });
|
||||
})
|
||||
.catch(error => {
|
||||
.catch((error) => {
|
||||
setBookmarkData({ groups: [], error: error.message });
|
||||
});
|
||||
}, []);
|
||||
|
@ -66,7 +66,7 @@ const useBookmarkData = () => {
|
|||
|
||||
const BookmarkList = () => {
|
||||
const {
|
||||
bookmarkData: { groups, error }
|
||||
bookmarkData: { groups, error },
|
||||
} = useBookmarkData();
|
||||
return (
|
||||
<ListContainer>
|
||||
|
|
|
@ -5,7 +5,7 @@ import MaterialIcon from 'material-icons-react';
|
|||
|
||||
// File for elements that are/can be reused across the entire site.
|
||||
|
||||
export const handleResponse = response => {
|
||||
export const handleResponse = (response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
|
@ -13,12 +13,11 @@ export const handleResponse = response => {
|
|||
};
|
||||
|
||||
export const ListContainer = styled.div`
|
||||
padding: 2rem 0 2rem 0;
|
||||
padding: 2rem 0;
|
||||
`;
|
||||
|
||||
export const Headline = styled.h3`
|
||||
display: inline-block;
|
||||
font-family: Roboto, sans-serif;
|
||||
font-weight: 900;
|
||||
text-transform: uppercase;
|
||||
margin: 0px;
|
||||
|
@ -26,6 +25,15 @@ export const Headline = styled.h3`
|
|||
color: ${selectedTheme.mainColor};
|
||||
`;
|
||||
|
||||
export const SubHeadline = styled.h4`
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
margin: 0px;
|
||||
font-size: 1.5rem;
|
||||
color: ${selectedTheme.mainColor};
|
||||
`;
|
||||
|
||||
export const ItemList = styled.ul`
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
|
@ -41,7 +49,6 @@ export const Item = styled.li`
|
|||
`;
|
||||
|
||||
export const Button = styled.button`
|
||||
font-family: Roboto, sans-serif;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
border: 1px solid ${selectedTheme.mainColor};
|
||||
|
@ -75,7 +82,7 @@ export const ErrorMessage = styled.p`
|
|||
color: red;
|
||||
`;
|
||||
|
||||
export const IconButton = props => {
|
||||
export const IconButton = (props) => {
|
||||
if (
|
||||
props.icon &&
|
||||
props.icon !== '' &&
|
||||
|
|
|
@ -4,19 +4,17 @@ import styled from 'styled-components';
|
|||
import selectedTheme from './themeManager';
|
||||
|
||||
const GreeterContainer = styled.div`
|
||||
padding: 2rem 0 2rem 0;
|
||||
padding: 2rem 0;
|
||||
`;
|
||||
|
||||
const GreetText = styled.h1`
|
||||
font-family: Roboto, sans-serif;
|
||||
font-weight: 900;
|
||||
font-size: 45px;
|
||||
margin: 0.5rem 0 0.5rem 0;
|
||||
margin: 0.5rem 0;
|
||||
color: ${selectedTheme.mainColor};
|
||||
`;
|
||||
|
||||
const DateText = styled.h3`
|
||||
font-family: Roboto, sans-serif;
|
||||
font-weight: 400;
|
||||
font-size: 15px;
|
||||
text-transform: uppercase;
|
||||
|
@ -39,7 +37,7 @@ const getGreeting = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const getExtension = day => {
|
||||
const getExtension = (day) => {
|
||||
let extension = '';
|
||||
|
||||
if ((day > 4 && day <= 20) || (day > 20 && day % 10 >= 4)) {
|
||||
|
@ -67,7 +65,7 @@ const monthNames = [
|
|||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December'
|
||||
'December',
|
||||
];
|
||||
|
||||
const weekDayNames = [
|
||||
|
@ -77,7 +75,7 @@ const weekDayNames = [
|
|||
'Wednesday',
|
||||
'Thursday',
|
||||
'Friday',
|
||||
'Saturday'
|
||||
'Saturday',
|
||||
];
|
||||
|
||||
const getDateString = () => {
|
||||
|
|
|
@ -11,11 +11,11 @@ import {
|
|||
Button,
|
||||
IconButton,
|
||||
ErrorMessage,
|
||||
Headline as hl
|
||||
Headline as hl,
|
||||
} from './elements';
|
||||
|
||||
const Headline = styled(hl)`
|
||||
padding: 0.5rem 0 0.5rem 0;
|
||||
padding: 0.5rem 0;
|
||||
`;
|
||||
|
||||
const Modal = styled.div`
|
||||
|
@ -60,9 +60,8 @@ const HeadCell = styled.th`
|
|||
`;
|
||||
|
||||
const SelectorStyle = {
|
||||
control: provided => ({
|
||||
control: (provided) => ({
|
||||
...provided,
|
||||
fontFamily: 'Roboto, sans-serif',
|
||||
fontWeight: '500',
|
||||
color: selectedTheme.mainColor,
|
||||
textTransform: 'uppercase',
|
||||
|
@ -72,19 +71,18 @@ const SelectorStyle = {
|
|||
border: '1px solid ' + selectedTheme.mainColor,
|
||||
boxShadow: 0,
|
||||
'&:hover': {
|
||||
border: '1px solid ' + selectedTheme.mainColor
|
||||
}
|
||||
border: '1px solid ' + selectedTheme.mainColor,
|
||||
},
|
||||
}),
|
||||
menu: provided => ({
|
||||
menu: (provided) => ({
|
||||
...provided,
|
||||
backgroundColor: selectedTheme.backgroundColor,
|
||||
border: '1px solid ' + selectedTheme.mainColor,
|
||||
borderRadius: '0px',
|
||||
boxShadow: 0
|
||||
boxShadow: 0,
|
||||
}),
|
||||
option: provided => ({
|
||||
option: (provided) => ({
|
||||
...provided,
|
||||
fontFamily: 'Roboto, sans-serif',
|
||||
fontWeight: '500',
|
||||
color: selectedTheme.mainColor,
|
||||
textTransform: 'uppercase',
|
||||
|
@ -93,15 +91,15 @@ const SelectorStyle = {
|
|||
backgroundColor: selectedTheme.backgroundColor,
|
||||
'&:hover': {
|
||||
backgroundColor: selectedTheme.mainColor,
|
||||
color: selectedTheme.backgroundColor
|
||||
}
|
||||
color: selectedTheme.backgroundColor,
|
||||
},
|
||||
}),
|
||||
singleValue: provided => {
|
||||
singleValue: (provided) => {
|
||||
return {
|
||||
...provided,
|
||||
color: selectedTheme.mainColor
|
||||
color: selectedTheme.mainColor,
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const useThemeData = () => {
|
||||
|
@ -112,10 +110,10 @@ const useThemeData = () => {
|
|||
? fetch('/data/themes.json').then(handleResponse)
|
||||
: import('./data/themes.json')
|
||||
)
|
||||
.then(jsonResponse => {
|
||||
.then((jsonResponse) => {
|
||||
setThemeData({ ...jsonResponse, error: false });
|
||||
})
|
||||
.catch(error => {
|
||||
.catch((error) => {
|
||||
setThemeData({ themes: [], error: error.message });
|
||||
});
|
||||
}, []);
|
||||
|
@ -131,7 +129,7 @@ const SettingsModal = () => {
|
|||
const [newTheme, setNewTheme] = useState();
|
||||
|
||||
const {
|
||||
themeData: { themes, error }
|
||||
themeData: { themes, error },
|
||||
} = useThemeData();
|
||||
|
||||
return (
|
||||
|
@ -152,7 +150,7 @@ const SettingsModal = () => {
|
|||
<Select
|
||||
options={themes}
|
||||
defaultValue={selectedTheme}
|
||||
onChange={e => {
|
||||
onChange={(e) => {
|
||||
setNewTheme(e);
|
||||
}}
|
||||
styles={SelectorStyle}
|
||||
|
|
Loading…
Reference in a new issue