Skip to content

Commit 004a569

Browse files
committed
Nicer errors when managing files
1 parent 88374de commit 004a569

File tree

2 files changed

+58
-12
lines changed

2 files changed

+58
-12
lines changed

resources/scripts/components/screens/ServerError.tsx

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,55 @@ import React from 'react';
22
import PageContentBlock from '@/components/elements/PageContentBlock';
33
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
44
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons/faArrowLeft';
5+
import { faSyncAlt } from '@fortawesome/free-solid-svg-icons/faSyncAlt';
6+
import classNames from 'classnames';
7+
import styled from 'styled-components';
58

6-
interface Props {
9+
interface BaseProps {
710
title?: string;
811
message: string;
12+
onRetry?: () => void;
913
onBack?: () => void;
1014
}
1115

12-
export default ({ title, message, onBack }: Props) => (
16+
interface PropsWithRetry extends BaseProps {
17+
onRetry?: () => void;
18+
onBack?: never | undefined;
19+
}
20+
21+
interface PropsWithBack extends BaseProps {
22+
onBack?: () => void;
23+
onRetry?: never | undefined;
24+
}
25+
26+
type Props = PropsWithBack | PropsWithRetry;
27+
28+
const ActionButton = styled.button`
29+
${tw`rounded-full w-8 h-8 flex items-center justify-center`};
30+
31+
&.hover\\:spin:hover {
32+
animation: spin 2s linear infinite;
33+
}
34+
35+
@keyframes spin {
36+
to {
37+
transform: rotate(360deg);
38+
}
39+
}
40+
`;
41+
42+
export default ({ title, message, onBack, onRetry }: Props) => (
1343
<PageContentBlock>
1444
<div className={'flex justify-center'}>
1545
<div className={'w-full sm:w-3/4 md:w-1/2 p-12 md:p-20 bg-neutral-100 rounded-lg shadow-lg text-center relative'}>
16-
{typeof onBack === 'function' &&
46+
{(typeof onBack === 'function' || typeof onRetry === 'function') &&
1747
<div className={'absolute pin-l pin-t ml-4 mt-4'}>
18-
<button
19-
onClick={() => onBack()}
20-
className={'rounded-full btn btn-primary w-8 h-8 flex items-center justify-center'}
48+
<ActionButton
49+
onClick={() => onRetry ? onRetry() : (onBack ? onBack() : null)}
50+
className={classNames('btn btn-primary', { 'hover:spin': !!onRetry })}
2151
>
22-
<FontAwesomeIcon icon={faArrowLeft}/>
23-
</button>
52+
<FontAwesomeIcon icon={onRetry ? faSyncAlt : faArrowLeft}/>
53+
</ActionButton>
2454
</div>
2555
}
2656
<img src={'/assets/svgs/server_error.svg'} className={'w-2/3 h-auto select-none'}/>

resources/scripts/components/server/files/FileManagerContainer.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,47 @@ import NewDirectoryButton from '@/components/server/files/NewDirectoryButton';
1313
import { Link } from 'react-router-dom';
1414
import Can from '@/components/elements/Can';
1515
import PageContentBlock from '@/components/elements/PageContentBlock';
16+
import ServerError from '@/components/screens/ServerError';
17+
import useRouter from 'use-react-router';
1618

1719
const sortFiles = (files: FileObject[]): FileObject[] => {
1820
return files.sort((a, b) => a.name.localeCompare(b.name))
1921
.sort((a, b) => a.isFile === b.isFile ? 0 : (a.isFile ? 1 : -1));
2022
};
2123

2224
export default () => {
25+
const [ error, setError ] = useState('');
2326
const [ loading, setLoading ] = useState(true);
2427
const { addError, clearFlashes } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
2528
const { id } = ServerContext.useStoreState(state => state.server.data!);
2629
const { contents: files } = ServerContext.useStoreState(state => state.files);
2730
const { getDirectoryContents } = ServerContext.useStoreActions(actions => actions.files);
2831

29-
useEffect(() => {
30-
setLoading(true);
32+
const loadContents = () => {
33+
setError('');
3134
clearFlashes();
32-
35+
setLoading(true);
3336
getDirectoryContents(window.location.hash)
3437
.then(() => setLoading(false))
3538
.catch(error => {
3639
console.error(error.message, { error });
37-
addError({ message: httpErrorToHuman(error), key: 'files' });
40+
setError(httpErrorToHuman(error));
3841
});
42+
};
43+
44+
useEffect(() => {
45+
loadContents();
3946
}, []);
4047

48+
if (error) {
49+
return (
50+
<ServerError
51+
message={error}
52+
onRetry={() => loadContents()}
53+
/>
54+
);
55+
}
56+
4157
return (
4258
<PageContentBlock>
4359
<FlashMessageRender byKey={'files'} className={'mb-4'}/>

0 commit comments

Comments
 (0)