Refactored codebase
This commit is contained in:
parent
9c372553f9
commit
c7ef96b412
6 changed files with 227 additions and 109 deletions
55
src/components/app.js
Normal file
55
src/components/app.js
Normal file
|
@ -0,0 +1,55 @@
|
|||
import React from 'react';
|
||||
import MaterialIcon from 'material-icons-react';
|
||||
import styled from 'styled-components';
|
||||
import selectedTheme from './themeManager';
|
||||
|
||||
const AppContainer = styled.div`
|
||||
display: flex;
|
||||
flex: auto 25%;
|
||||
padding: 1rem;
|
||||
`;
|
||||
|
||||
const IconContainer = styled.div`
|
||||
margin-right: 0.5vh;
|
||||
`;
|
||||
|
||||
const DetailsContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const AppLink = styled.a`
|
||||
font-family: Roboto, sans-serif;
|
||||
flex: 1 0 auto;
|
||||
color: ${selectedTheme.mainColor};
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
font-size: 1rem;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
`;
|
||||
|
||||
const AppDescription = styled.p`
|
||||
font-family: Roboto, sans-serif;
|
||||
text-transform: uppercase;
|
||||
margin: 0;
|
||||
font-size: 0.65rem;
|
||||
font-weight: 400;
|
||||
color: ${selectedTheme.accentColor};
|
||||
`;
|
||||
|
||||
export const App = ({ name, icon, url, displayURL }) => (
|
||||
<AppContainer>
|
||||
<IconContainer>
|
||||
<MaterialIcon icon={icon} color={selectedTheme.mainColor} />
|
||||
</IconContainer>
|
||||
<DetailsContainer>
|
||||
<AppLink href={url}>{name}</AppLink>
|
||||
<AppDescription>{displayURL}</AppDescription>
|
||||
</DetailsContainer>
|
||||
</AppContainer>
|
||||
);
|
|
@ -1,62 +1,16 @@
|
|||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import MaterialIcon from 'material-icons-react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import selectedTheme from './themeManager';
|
||||
import { App } from './app';
|
||||
import { Category } from './category';
|
||||
|
||||
import {
|
||||
handleResponse,
|
||||
Headline,
|
||||
SubHeadline,
|
||||
ListContainer,
|
||||
ItemList,
|
||||
Item,
|
||||
ErrorMessage,
|
||||
} from './elements';
|
||||
|
||||
const IconContainer = styled.div`
|
||||
margin-right: 0.5vh;
|
||||
`;
|
||||
|
||||
const DetailsContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const Link = styled.a`
|
||||
font-family: Roboto, sans-serif;
|
||||
flex: 1 0 auto;
|
||||
color: ${selectedTheme.mainColor};
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
font-size: 1rem;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
`;
|
||||
|
||||
const Description = styled.p`
|
||||
font-family: Roboto, sans-serif;
|
||||
text-transform: uppercase;
|
||||
margin: 0;
|
||||
font-size: 0.65rem;
|
||||
font-weight: 400;
|
||||
color: ${selectedTheme.accentColor};
|
||||
`;
|
||||
|
||||
const CategoryContainer = styled.div`
|
||||
padding: 1rem 0;
|
||||
`;
|
||||
|
||||
const App = styled.div`
|
||||
display: flex;
|
||||
flex: auto 25%;
|
||||
padding: 1rem;
|
||||
`;
|
||||
|
||||
const useAppData = () => {
|
||||
const [appData, setAppData] = useState({ apps: [], error: false });
|
||||
const fetchAppData = useCallback(() => {
|
||||
|
@ -86,58 +40,25 @@ const AppList = () => {
|
|||
<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
|
||||
}
|
||||
{categories &&
|
||||
categories.map((category, idx) => (
|
||||
<Category
|
||||
key={[category.name, idx].join('')}
|
||||
name={category.name}
|
||||
items={category.items}
|
||||
/>
|
||||
</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) => (
|
||||
<Item key={[app.name, idx].join('')}>
|
||||
<App>
|
||||
<IconContainer>
|
||||
<MaterialIcon
|
||||
<App
|
||||
name={app.name}
|
||||
icon={app.icon}
|
||||
color={selectedTheme.mainColor}
|
||||
url={app.url}
|
||||
displayURL={app.displayURL}
|
||||
/>
|
||||
</IconContainer>
|
||||
<DetailsContainer>
|
||||
<Link href={app.URL}>{app.name}</Link>
|
||||
<Description>{app.displayURL}</Description>
|
||||
</DetailsContainer>
|
||||
</App>
|
||||
</Item>
|
||||
))}
|
||||
</ItemList>
|
||||
|
|
|
@ -5,20 +5,13 @@ import selectedTheme from './themeManager';
|
|||
import {
|
||||
handleResponse,
|
||||
Headline,
|
||||
SubHeadline,
|
||||
ListContainer,
|
||||
ItemList,
|
||||
Item,
|
||||
ErrorMessage,
|
||||
} from './elements';
|
||||
|
||||
const Group = styled.h4`
|
||||
font-family: Roboto, sans-serif;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
text-transform: uppercase;
|
||||
color: ${selectedTheme.mainColor};
|
||||
`;
|
||||
|
||||
const BookmarkGroup = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -27,7 +20,6 @@ const BookmarkGroup = styled.div`
|
|||
`;
|
||||
|
||||
const Bookmark = styled.a`
|
||||
font-family: Roboto, sans-serif;
|
||||
font-weight: 400;
|
||||
text-decoration: none;
|
||||
color: ${selectedTheme.accentColor};
|
||||
|
@ -77,7 +69,7 @@ const BookmarkList = () => {
|
|||
return (
|
||||
<Item key={[group.name, idx].join('')}>
|
||||
<BookmarkGroup>
|
||||
<Group>{group.name}</Group>
|
||||
<SubHeadline>{group.name}</SubHeadline>
|
||||
{group.items.map(({ url, name: linkName }) => (
|
||||
<Bookmark key={linkName} href={url}>
|
||||
{linkName}
|
||||
|
|
31
src/components/category.js
Normal file
31
src/components/category.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { App } from './app';
|
||||
import { ItemList, Item, SubHeadline } from './elements';
|
||||
|
||||
const CategoryHeadline = styled(SubHeadline)`
|
||||
font-size: 1.25rem;
|
||||
`;
|
||||
|
||||
const CategoryContainer = styled.div`
|
||||
width: 100%;
|
||||
padding-top: 1rem;
|
||||
`;
|
||||
|
||||
export const Category = ({ name, items }) => (
|
||||
<CategoryContainer>
|
||||
<CategoryHeadline>{name}</CategoryHeadline>
|
||||
<ItemList>
|
||||
{items.map((app, idx) => (
|
||||
<Item key={[app.name, idx].join('')}>
|
||||
<App
|
||||
name={app.name}
|
||||
icon={app.icon}
|
||||
url={app.url}
|
||||
displayURL={app.displayURL}
|
||||
/>
|
||||
</Item>
|
||||
))}
|
||||
</ItemList>
|
||||
</CategoryContainer>
|
||||
);
|
|
@ -1,4 +1,124 @@
|
|||
{
|
||||
"categories": [
|
||||
{
|
||||
"name": "Test",
|
||||
"items": [
|
||||
{
|
||||
"name": "Pihole",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "vpn_lock"
|
||||
},
|
||||
{
|
||||
"name": "Plex",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "tv"
|
||||
},
|
||||
{
|
||||
"name": "NextCloud",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "filter_drama"
|
||||
},
|
||||
{
|
||||
"name": "Ghost",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "rss_feed"
|
||||
},
|
||||
{
|
||||
"name": "Minecraft",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "games"
|
||||
},
|
||||
{
|
||||
"name": "pfSense",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "security"
|
||||
},
|
||||
{
|
||||
"name": "ESXi",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "dns"
|
||||
},
|
||||
{
|
||||
"name": "Tautulli",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "bar_chart"
|
||||
},
|
||||
{
|
||||
"name": "Grafana",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "show_chart"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Test again",
|
||||
"items": [
|
||||
{
|
||||
"name": "Pihole",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "vpn_lock"
|
||||
},
|
||||
{
|
||||
"name": "Plex",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "tv"
|
||||
},
|
||||
{
|
||||
"name": "NextCloud",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "filter_drama"
|
||||
},
|
||||
{
|
||||
"name": "Ghost",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "rss_feed"
|
||||
},
|
||||
{
|
||||
"name": "Minecraft",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "games"
|
||||
},
|
||||
{
|
||||
"name": "pfSense",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "security"
|
||||
},
|
||||
{
|
||||
"name": "ESXi",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "dns"
|
||||
},
|
||||
{
|
||||
"name": "Tautulli",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "bar_chart"
|
||||
},
|
||||
{
|
||||
"name": "Grafana",
|
||||
"displayURL": "example.com",
|
||||
"URL": "https://example.com",
|
||||
"icon": "show_chart"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"apps": [
|
||||
{
|
||||
"name": "Pihole",
|
||||
|
|
|
@ -16,7 +16,7 @@ export const ListContainer = styled.div`
|
|||
padding: 2rem 0;
|
||||
`;
|
||||
|
||||
export const Headline = styled.h3`
|
||||
export const Headline = styled.h2`
|
||||
display: inline-block;
|
||||
font-weight: 900;
|
||||
text-transform: uppercase;
|
||||
|
@ -25,12 +25,11 @@ export const Headline = styled.h3`
|
|||
color: ${selectedTheme.mainColor};
|
||||
`;
|
||||
|
||||
export const SubHeadline = styled.h4`
|
||||
export const SubHeadline = styled.h3`
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
margin: 0px;
|
||||
font-size: 1.5rem;
|
||||
margin: 0;
|
||||
color: ${selectedTheme.mainColor};
|
||||
`;
|
||||
|
||||
|
|
Loading…
Reference in a new issue