Added production support for themes
also some css improvements
This commit is contained in:
parent
a82bdc1620
commit
c2d5a90df5
5 changed files with 75 additions and 23 deletions
|
@ -4,7 +4,14 @@ import styled from 'styled-components';
|
||||||
|
|
||||||
import selectedTheme from './themeManager';
|
import selectedTheme from './themeManager';
|
||||||
|
|
||||||
import { Headline, ListContainer, ItemList, Item, RefreshButton, ErrorMessage } from './elements';
|
import {
|
||||||
|
Headline,
|
||||||
|
ListContainer,
|
||||||
|
ItemList,
|
||||||
|
Item,
|
||||||
|
RefreshButton,
|
||||||
|
ErrorMessage
|
||||||
|
} from './elements';
|
||||||
|
|
||||||
const IconContainer = styled.div`
|
const IconContainer = styled.div`
|
||||||
margin-right: 0.5vh;
|
margin-right: 0.5vh;
|
||||||
|
@ -41,14 +48,14 @@ const App = styled.div`
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function handleResponse(response) {
|
const handleResponse = response => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
throw new Error('Failed to load app data.');
|
throw new Error('Failed to load app data.');
|
||||||
}
|
};
|
||||||
|
|
||||||
function useAppData() {
|
const useAppData = () => {
|
||||||
const [appData, setAppData] = useState({ apps: [], error: false });
|
const [appData, setAppData] = useState({ apps: [], error: false });
|
||||||
const fetchAppData = useCallback(() => {
|
const fetchAppData = useCallback(() => {
|
||||||
(process.env.NODE_ENV === 'production'
|
(process.env.NODE_ENV === 'production'
|
||||||
|
@ -63,15 +70,11 @@ function useAppData() {
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
console.log(appData)
|
|
||||||
}, [appData]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchAppData();
|
fetchAppData();
|
||||||
}, [fetchAppData]);
|
}, [fetchAppData]);
|
||||||
return { appData, fetchAppData };
|
return { appData, fetchAppData };
|
||||||
}
|
};
|
||||||
|
|
||||||
const AppList = () => {
|
const AppList = () => {
|
||||||
const {
|
const {
|
||||||
|
|
|
@ -2,7 +2,14 @@ import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import selectedTheme from './themeManager';
|
import selectedTheme from './themeManager';
|
||||||
import { Headline, ListContainer, ItemList, Item, RefreshButton, ErrorMessage } from './elements';
|
import {
|
||||||
|
Headline,
|
||||||
|
ListContainer,
|
||||||
|
ItemList,
|
||||||
|
Item,
|
||||||
|
RefreshButton,
|
||||||
|
ErrorMessage
|
||||||
|
} from './elements';
|
||||||
|
|
||||||
const Group = styled.h4`
|
const Group = styled.h4`
|
||||||
font-family: Roboto, sans-serif;
|
font-family: Roboto, sans-serif;
|
||||||
|
@ -28,15 +35,18 @@ const Bookmark = styled.a`
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function handleResponse(response) {
|
const handleResponse = response => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
throw new Error('Failed to load app data.');
|
throw new Error('Failed to load app data.');
|
||||||
}
|
};
|
||||||
|
|
||||||
const useBookmarkData = () => {
|
const useBookmarkData = () => {
|
||||||
const [bookmarkData, setBookmarkData] = useState({ groups: [], error: false });
|
const [bookmarkData, setBookmarkData] = useState({
|
||||||
|
groups: [],
|
||||||
|
error: false
|
||||||
|
});
|
||||||
const fetchBookmarkData = useCallback(() => {
|
const fetchBookmarkData = useCallback(() => {
|
||||||
(process.env.NODE_ENV === 'production'
|
(process.env.NODE_ENV === 'production'
|
||||||
? fetch('/bookmarks.json').then(handleResponse)
|
? fetch('/bookmarks.json').then(handleResponse)
|
||||||
|
@ -54,7 +64,7 @@ const useBookmarkData = () => {
|
||||||
fetchBookmarkData();
|
fetchBookmarkData();
|
||||||
}, [fetchBookmarkData]);
|
}, [fetchBookmarkData]);
|
||||||
return { bookmarkData, fetchBookmarkData };
|
return { bookmarkData, fetchBookmarkData };
|
||||||
}
|
};
|
||||||
|
|
||||||
const BookmarkList = () => {
|
const BookmarkList = () => {
|
||||||
const {
|
const {
|
||||||
|
@ -63,7 +73,7 @@ const BookmarkList = () => {
|
||||||
} = useBookmarkData();
|
} = useBookmarkData();
|
||||||
return (
|
return (
|
||||||
<ListContainer>
|
<ListContainer>
|
||||||
<Headline>Applications</Headline>
|
<Headline>Bookmarks</Headline>
|
||||||
<RefreshButton onClick={fetchBookmarkData}>refresh</RefreshButton>
|
<RefreshButton onClick={fetchBookmarkData}>refresh</RefreshButton>
|
||||||
<ItemList>
|
<ItemList>
|
||||||
{error && <ErrorMessage>{error}</ErrorMessage>}
|
{error && <ErrorMessage>{error}</ErrorMessage>}
|
||||||
|
|
|
@ -28,7 +28,6 @@ export const ItemList = styled.ul`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Item = styled.li`
|
export const Item = styled.li`
|
||||||
max-height: 100px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import Select from 'react-select';
|
import Select from 'react-select';
|
||||||
|
|
||||||
import searchData from './data/search.json';
|
import searchData from './data/search.json';
|
||||||
import themeData from './data/themes.json';
|
|
||||||
|
|
||||||
import selectedTheme, { setTheme } from './themeManager';
|
import selectedTheme, { setTheme } from './themeManager';
|
||||||
import { Button, IconButton } from './elements';
|
import { Button, IconButton, ErrorMessage } from './elements';
|
||||||
|
|
||||||
const Modal = styled.div`
|
const Modal = styled.div`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -103,10 +102,43 @@ const SelectorStyle = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleResponse = response => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
throw new Error('Failed to load app data.');
|
||||||
|
};
|
||||||
|
|
||||||
|
const useThemeData = () => {
|
||||||
|
const [themeData, setThemeData] = useState({ themes: [], error: false });
|
||||||
|
const fetchThemeData = useCallback(() => {
|
||||||
|
(process.env.NODE_ENV === 'production'
|
||||||
|
? fetch('/themes.json').then(handleResponse)
|
||||||
|
: import('./data/themes.json')
|
||||||
|
)
|
||||||
|
.then(jsonResponse => {
|
||||||
|
setThemeData({ ...jsonResponse, error: false });
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
setThemeData({ themes: [], error: error.message });
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchThemeData();
|
||||||
|
}, [fetchThemeData]);
|
||||||
|
return { themeData, fetchThemeData };
|
||||||
|
};
|
||||||
|
|
||||||
const SettingsModal = () => {
|
const SettingsModal = () => {
|
||||||
const [modalHidden, setModalHidden] = useState(true);
|
const [modalHidden, setModalHidden] = useState(true);
|
||||||
const [newTheme, setNewTheme] = useState();
|
const [newTheme, setNewTheme] = useState();
|
||||||
|
|
||||||
|
const {
|
||||||
|
themeData: { themes, error },
|
||||||
|
fetchThemeData
|
||||||
|
} = useThemeData();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
@ -118,17 +150,19 @@ const SettingsModal = () => {
|
||||||
icon="close"
|
icon="close"
|
||||||
onClick={() => setModalHidden(!modalHidden)}
|
onClick={() => setModalHidden(!modalHidden)}
|
||||||
/>
|
/>
|
||||||
|
{error && <ErrorMessage>{error}</ErrorMessage>}
|
||||||
<SelectContainer>
|
<SelectContainer>
|
||||||
<Headline>Theme:</Headline>
|
<Headline>Theme:</Headline>
|
||||||
<FormContainer>
|
<FormContainer>
|
||||||
<Select
|
<Select
|
||||||
options={themeData.themes}
|
options={themes}
|
||||||
defaultValue={selectedTheme}
|
defaultValue={selectedTheme}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
setNewTheme(e);
|
setNewTheme(e);
|
||||||
}}
|
}}
|
||||||
styles={SelectorStyle}
|
styles={SelectorStyle}
|
||||||
/>
|
/>
|
||||||
|
<Button onClick={fetchThemeData}>Refresh</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setTheme(JSON.stringify(newTheme))}
|
onClick={() => setTheme(JSON.stringify(newTheme))}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
import themeData from './data/themes.json';
|
const defaultTheme = {
|
||||||
|
label: 'Classic',
|
||||||
|
value: 0,
|
||||||
|
mainColor: '#000000',
|
||||||
|
accentColor: '#1e272e',
|
||||||
|
backgroundColor: '#ffffff'
|
||||||
|
};
|
||||||
|
|
||||||
const setTheme = theme => {
|
const setTheme = theme => {
|
||||||
localStorage.setItem('theme', theme);
|
localStorage.setItem('theme', theme);
|
||||||
|
@ -10,7 +16,7 @@ const resetTheme = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTheme = () => {
|
const getTheme = () => {
|
||||||
let selectedTheme = themeData.themes[0];
|
let selectedTheme = defaultTheme;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
localStorage.getItem('theme') &&
|
localStorage.getItem('theme') &&
|
||||||
|
|
Loading…
Reference in a new issue