From 004a5692cff63f3fe9937013367ee5acb9f68bd6 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Fri, 17 Apr 2020 11:45:20 -0700 Subject: [PATCH] Nicer errors when managing files --- .../components/screens/ServerError.tsx | 46 +++++++++++++++---- .../server/files/FileManagerContainer.tsx | 24 ++++++++-- 2 files changed, 58 insertions(+), 12 deletions(-) diff --git a/resources/scripts/components/screens/ServerError.tsx b/resources/scripts/components/screens/ServerError.tsx index 97f091c4d..a5a9f8d53 100644 --- a/resources/scripts/components/screens/ServerError.tsx +++ b/resources/scripts/components/screens/ServerError.tsx @@ -2,25 +2,55 @@ import React from 'react'; import PageContentBlock from '@/components/elements/PageContentBlock'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faArrowLeft } from '@fortawesome/free-solid-svg-icons/faArrowLeft'; +import { faSyncAlt } from '@fortawesome/free-solid-svg-icons/faSyncAlt'; +import classNames from 'classnames'; +import styled from 'styled-components'; -interface Props { +interface BaseProps { title?: string; message: string; + onRetry?: () => void; onBack?: () => void; } -export default ({ title, message, onBack }: Props) => ( +interface PropsWithRetry extends BaseProps { + onRetry?: () => void; + onBack?: never | undefined; +} + +interface PropsWithBack extends BaseProps { + onBack?: () => void; + onRetry?: never | undefined; +} + +type Props = PropsWithBack | PropsWithRetry; + +const ActionButton = styled.button` + ${tw`rounded-full w-8 h-8 flex items-center justify-center`}; + + &.hover\\:spin:hover { + animation: spin 2s linear infinite; + } + + @keyframes spin { + to { + transform: rotate(360deg); + } + } +`; + +export default ({ title, message, onBack, onRetry }: Props) => (
- {typeof onBack === 'function' && + {(typeof onBack === 'function' || typeof onRetry === 'function') &&
- + +
} diff --git a/resources/scripts/components/server/files/FileManagerContainer.tsx b/resources/scripts/components/server/files/FileManagerContainer.tsx index 0b3c99382..2e0298dce 100644 --- a/resources/scripts/components/server/files/FileManagerContainer.tsx +++ b/resources/scripts/components/server/files/FileManagerContainer.tsx @@ -13,6 +13,8 @@ import NewDirectoryButton from '@/components/server/files/NewDirectoryButton'; import { Link } from 'react-router-dom'; import Can from '@/components/elements/Can'; import PageContentBlock from '@/components/elements/PageContentBlock'; +import ServerError from '@/components/screens/ServerError'; +import useRouter from 'use-react-router'; const sortFiles = (files: FileObject[]): FileObject[] => { return files.sort((a, b) => a.name.localeCompare(b.name)) @@ -20,24 +22,38 @@ const sortFiles = (files: FileObject[]): FileObject[] => { }; export default () => { + const [ error, setError ] = useState(''); const [ loading, setLoading ] = useState(true); const { addError, clearFlashes } = useStoreActions((actions: Actions) => actions.flashes); const { id } = ServerContext.useStoreState(state => state.server.data!); const { contents: files } = ServerContext.useStoreState(state => state.files); const { getDirectoryContents } = ServerContext.useStoreActions(actions => actions.files); - useEffect(() => { - setLoading(true); + const loadContents = () => { + setError(''); clearFlashes(); - + setLoading(true); getDirectoryContents(window.location.hash) .then(() => setLoading(false)) .catch(error => { console.error(error.message, { error }); - addError({ message: httpErrorToHuman(error), key: 'files' }); + setError(httpErrorToHuman(error)); }); + }; + + useEffect(() => { + loadContents(); }, []); + if (error) { + return ( + loadContents()} + /> + ); + } + return (