Skip to content

#30 Make installable and better error handling #255

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ publish
.nohup
*/lib
*/dist
*/dev-dist
*/yarn-error.log
test-results
*/nohup.out
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This changelog covers all three packages, as they are (for now) updated as a who
- Add folders with list & grid views, allow drag & drop uploads #228
- Show icons in sidebar
- Add scoped search, funded by NGI NLnet Discovery #245
- Make web app installable #30
- Add cookie based authentication #241

## v0.32.1
Expand Down
27 changes: 6 additions & 21 deletions data-browser/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
<link href="/apple-touch-icon.png" rel="apple-touch-icon" sizes="180x180" />
<link href="/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png" />
<link href="/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png" />
<link href="/site.webmanifest" rel="manifest" />
<link color="#1e43a3" href="/safari-pinned-tab.svg" rel="mask-icon" />
<link color="#1e43a3" href="/mask-icon.svg" rel="mask-icon" />
<meta content="yes" name="apple-mobile-web-app-capable" />
<meta content="yes" name="mobile-web-app-capable" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="dns-prefetch" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://fonts.gstatic.com">
<link rel="preconnect" crossorigin="anonymous" href="https://fonts.googleapis.com">
<link rel="preconnect" crossorigin="anonymous" href="https://fonts.gstatic.com">
<link
crossorigin="anonymous"
href="https://fonts.googleapis.com/css2?family=Montserrat:wght@700&family=Open+Sans:ital,wght@0,400;0,700;1,400;1,700&display=swap"
rel="stylesheet">
<title>Atomic Data Browser</title>
Expand Down Expand Up @@ -89,23 +91,6 @@
.setProperty('--background-color', 'black');
}
</script>

<!-- Service worker -->
<script>
const registerServiceWorker = async () => {
if ('serviceWorker' in navigator) {
try {
await navigator.serviceWorker.register('/sw.js', {
scope: '/',
});
} catch (error) {
console.error(`Registration failed with ${error}`);
}
}
};

registerServiceWorker();
</script>
</body>

</html>
4 changes: 3 additions & 1 deletion data-browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
"react-intersection-observer": "^8.31.1",
"react-is": "^18",
"react-markdown": "^8.0.3",
"react-router-dom": "^6.0.0",
"react-router": "^6.0.0",
"react-router-dom": "^6.0.0",
"remark-gfm": "^3.0.1",
"styled-components": "^5.3.3",
"yamde": "^1.7.1"
Expand All @@ -42,6 +42,8 @@
"gh-pages": "^3.1.0",
"lint-staged": "^10.5.4",
"types-wm": "^1.1.0",
"vite": "^3.0.5",
"vite-plugin-pwa": "^0.13.1",
"workbox-cli": "^6.4.1"
},
"homepage": "https://atomicdata.dev/",
Expand Down
Binary file added data-browser/public/maskable_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data-browser/public/maskable_icon_x128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data-browser/public/maskable_icon_x192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data-browser/public/maskable_icon_x384.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data-browser/public/maskable_icon_x512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions data-browser/public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
User-agent: *
Allow: /
20 changes: 0 additions & 20 deletions data-browser/public/site.webmanifest

This file was deleted.

3 changes: 0 additions & 3 deletions data-browser/public/sw.js

This file was deleted.

21 changes: 14 additions & 7 deletions data-browser/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ import toast from 'react-hot-toast';
import { DialogContainer } from './components/Dialog/DialogContainer';
import { registerHandlers } from './handlers';
import { ErrorBoundary } from './views/ErrorPage';
import { NetworkIndicator } from './components/NetworkIndicator';

function fixDevUrl(url: string) {
if (isDev()) {
return url.replace('5173', '9883');
}

return url;
}

/** Initialize the store */
const store = new Store();
Expand All @@ -30,11 +39,8 @@ const store = new Store();
* In dev envs, we want to default to port 9883
*/
const currentOrigin = window.location.origin;
store.setServerUrl(
currentOrigin === 'http://localhost:5173'
? 'http://localhost:9883'
: currentOrigin,
);

store.setServerUrl(fixDevUrl(currentOrigin));

/** Show an error when things go wrong */
store.errorHandler = e => {
Expand Down Expand Up @@ -86,16 +92,17 @@ function App(): JSX.Element {
<BrowserRouter basename='/'>
<HotKeysWrapper>
<ThemeWrapper>
{/* @ts-ignore TODO: Check if types are fixed or upgrade styled-components to 6.0.0 */}
<GlobalStyle />
{/* @ts-ignore fallback component type too strict */}
<ErrBoundary FallbackComponent={CrashPage}>
{/* @ts-ignore TODO: Check if types are fixed or upgrade styled-components to 6.0.0 */}
<GlobalStyle />
<Toaster />
<MetaSetter />
<DialogContainer>
<NavWrapper>
<AppRoutes />
</NavWrapper>
<NetworkIndicator />
</DialogContainer>
</ErrBoundary>
</ThemeWrapper>
Expand Down
6 changes: 0 additions & 6 deletions data-browser/src/components/ErrorLook.ts

This file was deleted.

62 changes: 62 additions & 0 deletions data-browser/src/components/ErrorLook.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { lighten } from 'polished';
import styled from 'styled-components';
import React from 'react';
import { Details } from './Details';
import { FaExclamationTriangle } from 'react-icons/fa';

export const ErrorLook = styled.span`
color: ${props => props.theme.colors.alert};
font-family: monospace;
`;

export interface ErrorBlockProps {
error: Error;
showTrace?: boolean;
}

export function ErrorBlock({ error, showTrace }: ErrorBlockProps): JSX.Element {
return (
<ErrorLookBig>
<BiggerText>
<FaExclamationTriangle />
Something went wrong
</BiggerText>
<Details title={<span>Show Details</span>}>
<pre>
<CodeBlock>{error.message}</CodeBlock>
</pre>
{showTrace && (
<>
<span>Stack trace:</span>
<pre>
<CodeBlock>{error.stack}</CodeBlock>
</pre>
</>
)}
</Details>
</ErrorLookBig>
);
}

const ErrorLookBig = styled.div`
background-color: ${p => lighten(0.4, p.theme.colors.alert)};
color: ${p => p.theme.colors.alert};
font-size: 1rem;
padding: ${p => p.theme.margin}rem;
border-radius: ${p => p.theme.radius};
border: 1px solid ${p => lighten(0.2, p.theme.colors.alert)};
`;

const CodeBlock = styled.code`
white-space: pre-wrap;
border-radius: ${p => p.theme.radius};
padding: ${p => p.theme.margin}rem;
background-color: ${p => p.theme.colors.bg};
`;

const BiggerText = styled.p`
font-size: 1.3rem;
display: flex;
align-items: center;
gap: 1ch;
`;
29 changes: 18 additions & 11 deletions data-browser/src/components/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { shortcuts } from './HotKeyWrapper';
import { MenuBarDropdownTrigger } from './ResourceContextMenu/MenuBarDropdownTrigger';
import { NavBarSpacer } from './NavBarSpacer';
import { Searchbar } from './Searchbar';
import { useMediaQuery } from '../hooks/useMediaQuery';

interface NavWrapperProps {
children: React.ReactNode;
Expand Down Expand Up @@ -60,20 +61,26 @@ const Content = styled.div<ContentProps>`
`;

/** Persistently shown navigation bar */
function NavBar() {
function NavBar(): JSX.Element {
const [subject] = useCurrentSubject();
const navigate = useNavigate();
const { navbarTop, navbarFloating, sideBarLocked, setSideBarLocked } =
useSettings();
const [showButtons, setShowButtons] = React.useState<boolean>(true);

/** Checks if the app is running in PWA / stand alone mode or in a browser */
const isInStandaloneMode = () =>
window.matchMedia('(display-mode: standalone)').matches ||
// @ts-ignore standalone doesn't exist, but it does
window.navigator.standalone ||
document.referrer.includes('android-app://') ||
isRunningInTauri();
const machesStandalone = useMediaQuery(
'(display-mode: standalone) or (display-mode: fullscreen)',
);

const isInStandaloneMode = React.useMemo<boolean>(
() =>
machesStandalone ||
//@ts-ignore
window.navigator.standalone ||
document.referrer.includes('android-app://') ||
isRunningInTauri(),
[machesStandalone],
);

/** Hide buttons if the input element is quite small */
function maybeHideButtons(event: React.FocusEvent<HTMLInputElement>) {
Expand Down Expand Up @@ -101,19 +108,19 @@ function NavBar() {
>
<FaBars />
</ButtonBar>
{isInStandaloneMode() && (
{isInStandaloneMode && (
<>
<ButtonBar
type='button'
title='Go back'
onClick={() => navigate(1)}
onClick={() => navigate(-1)}
>
<FaArrowLeft />
</ButtonBar>{' '}
<ButtonBar
type='button'
title='Go forward'
onClick={() => navigate(-1)}
onClick={() => navigate(1)}
>
<FaArrowRight />
</ButtonBar>
Expand Down
63 changes: 63 additions & 0 deletions data-browser/src/components/NetworkIndicator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, { useEffect } from 'react';
import styled, { keyframes } from 'styled-components';
import { MdSignalWifiOff } from 'react-icons/md';
import { useOnline } from '../hooks/useOnline';
import { lighten } from 'polished';
import toast from 'react-hot-toast';

export function NetworkIndicator() {
const isOnline = useOnline();

useEffect(() => {
if (!isOnline) {
toast.error('You are offline, changes might not be persisted.');
}
}, [isOnline]);

return (
<Wrapper shown={!isOnline}>
<MdSignalWifiOff title='No Internet Connection.' />
</Wrapper>
);
}

interface WrapperProps {
shown: boolean;
}

const pulse = keyframes`
0% {
opacity: 1;
filter: drop-shadow(0 0 5px var(--shadow-color));
}
100% {
opacity: 0.8;
filter: drop-shadow(0 0 0 var(--shadow-color));
}
`;

const Wrapper = styled.div<WrapperProps>`
--shadow-color: ${p => lighten(0.15, p.theme.colors.alert)};
position: fixed;
bottom: 1.2rem;
right: 2rem;
z-index: ${({ theme }) => theme.zIndex.networkIndicator};
font-size: 1.5rem;
color: ${p => p.theme.colors.alert};
pointer-events: ${p => (p.shown ? 'auto' : 'none')};
transition: opacity 0.1s ease-in-out;
opacity: ${p => (p.shown ? 1 : 0)};

background-color: ${p => p.theme.colors.bg};
border: 1px solid ${p => p.theme.colors.alert};
border-radius: 50%;
display: grid;
place-items: center;
box-shadow: ${p => p.theme.boxShadowSoft};
padding: 0.5rem;

svg {
animation: ${pulse} 1.5s alternate ease-in-out infinite;
animation-play-state: ${p => (p.shown ? 'running' : 'paused')};
}
`;
7 changes: 5 additions & 2 deletions data-browser/src/components/Searchbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,11 @@ export function Searchbar({
);

useEffect(() => {
setInput(query?.toString());
setInputFocus();
setInput(query ?? '');

if (query || scope) {
setInputFocus();
}
}, [query, scope]);

return (
Expand Down
Loading