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