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 React, { useCallback, useEffect, useState } from 'react';
|
||||||
import MaterialIcon from 'material-icons-react';
|
import { App } from './app';
|
||||||
import styled from 'styled-components';
|
import { Category } from './category';
|
||||||
|
|
||||||
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`
|
|
||||||
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 useAppData = () => {
|
||||||
const [appData, setAppData] = useState({ apps: [], error: false });
|
const [appData, setAppData] = useState({ apps: [], error: false });
|
||||||
const fetchAppData = useCallback(() => {
|
const fetchAppData = useCallback(() => {
|
||||||
|
@ -86,58 +40,25 @@ const AppList = () => {
|
||||||
<ListContainer>
|
<ListContainer>
|
||||||
<Headline>Applications</Headline>
|
<Headline>Applications</Headline>
|
||||||
|
|
||||||
{categories && (
|
{categories &&
|
||||||
<CategoryContainer>
|
categories.map((category, idx) => (
|
||||||
{categories.map((category, idx) => (
|
<Category
|
||||||
<>
|
key={[category.name, idx].join('')}
|
||||||
<SubHeadline key={[category.name, idx].join('')}>
|
name={category.name}
|
||||||
{category.name}
|
items={category.items}
|
||||||
</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) => (
|
||||||
<Item key={[app.name, idx].join('')}>
|
<Item key={[app.name, idx].join('')}>
|
||||||
<App>
|
<App
|
||||||
<IconContainer>
|
name={app.name}
|
||||||
<MaterialIcon
|
icon={app.icon}
|
||||||
icon={app.icon}
|
url={app.url}
|
||||||
color={selectedTheme.mainColor}
|
displayURL={app.displayURL}
|
||||||
/>
|
/>
|
||||||
</IconContainer>
|
|
||||||
<DetailsContainer>
|
|
||||||
<Link href={app.URL}>{app.name}</Link>
|
|
||||||
<Description>{app.displayURL}</Description>
|
|
||||||
</DetailsContainer>
|
|
||||||
</App>
|
|
||||||
</Item>
|
</Item>
|
||||||
))}
|
))}
|
||||||
</ItemList>
|
</ItemList>
|
||||||
|
|
|
@ -5,20 +5,13 @@ import selectedTheme from './themeManager';
|
||||||
import {
|
import {
|
||||||
handleResponse,
|
handleResponse,
|
||||||
Headline,
|
Headline,
|
||||||
|
SubHeadline,
|
||||||
ListContainer,
|
ListContainer,
|
||||||
ItemList,
|
ItemList,
|
||||||
Item,
|
Item,
|
||||||
ErrorMessage,
|
ErrorMessage,
|
||||||
} from './elements';
|
} 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`
|
const BookmarkGroup = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -27,7 +20,6 @@ const BookmarkGroup = styled.div`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Bookmark = styled.a`
|
const Bookmark = styled.a`
|
||||||
font-family: Roboto, sans-serif;
|
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: ${selectedTheme.accentColor};
|
color: ${selectedTheme.accentColor};
|
||||||
|
@ -77,7 +69,7 @@ const BookmarkList = () => {
|
||||||
return (
|
return (
|
||||||
<Item key={[group.name, idx].join('')}>
|
<Item key={[group.name, idx].join('')}>
|
||||||
<BookmarkGroup>
|
<BookmarkGroup>
|
||||||
<Group>{group.name}</Group>
|
<SubHeadline>{group.name}</SubHeadline>
|
||||||
{group.items.map(({ url, name: linkName }) => (
|
{group.items.map(({ url, name: linkName }) => (
|
||||||
<Bookmark key={linkName} href={url}>
|
<Bookmark key={linkName} href={url}>
|
||||||
{linkName}
|
{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": [
|
"apps": [
|
||||||
{
|
{
|
||||||
"name": "Pihole",
|
"name": "Pihole",
|
||||||
|
|
|
@ -16,7 +16,7 @@ export const ListContainer = styled.div`
|
||||||
padding: 2rem 0;
|
padding: 2rem 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Headline = styled.h3`
|
export const Headline = styled.h2`
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
@ -25,12 +25,11 @@ export const Headline = styled.h3`
|
||||||
color: ${selectedTheme.mainColor};
|
color: ${selectedTheme.mainColor};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const SubHeadline = styled.h4`
|
export const SubHeadline = styled.h3`
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
margin: 0px;
|
margin: 0;
|
||||||
font-size: 1.5rem;
|
|
||||||
color: ${selectedTheme.mainColor};
|
color: ${selectedTheme.mainColor};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue