mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-12 23:36:00 +00:00
fix(app): unlimited loading screen when backend is not reachable (#364)
* Initial plan * Add error handling for unlimited loading screen bug Co-authored-by: antontranelis <31516529+antontranelis@users.noreply.github.com> * Complete fix for unlimited loading screen bug with proper state management Co-authored-by: antontranelis <31516529+antontranelis@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: antontranelis <31516529+antontranelis@users.noreply.github.com>
This commit is contained in:
parent
dbb405fe7e
commit
a9004a47ea
@ -71,6 +71,15 @@ function App() {
|
||||
const [layers, setLayers] = useState<any>()
|
||||
const [layerPageRoutes, setLayerPageRoutes] = useState<any>()
|
||||
const [loading, setLoading] = useState<boolean>(true)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
const retryConnection = () => {
|
||||
setError(null)
|
||||
setLoading(true)
|
||||
if (mapApiInstance) {
|
||||
getMap()
|
||||
}
|
||||
}
|
||||
|
||||
const [embedded, setEmbedded] = useState<boolean>(true)
|
||||
|
||||
@ -94,12 +103,27 @@ function App() {
|
||||
}, [mapApiInstance])
|
||||
|
||||
const getMap = async () => {
|
||||
try {
|
||||
const map = await mapApiInstance?.getItems()
|
||||
map && setMap(map)
|
||||
map && map != 'null' && setLayersApiInstance(new layersApi(map.id))
|
||||
map && map != 'null' && map.own_tag_space
|
||||
? setTagsApi(new itemsApi<Tag>('tags', undefined, map.id))
|
||||
: setTagsApi(new itemsApi<Tag>('tags'))
|
||||
// eslint-disable-next-line no-catch-all/no-catch-all
|
||||
} catch (error: any) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Failed to load map:', error)
|
||||
setError(
|
||||
typeof error === 'string'
|
||||
? error
|
||||
: error?.errors?.[0]?.message ||
|
||||
error?.message ||
|
||||
'Failed to connect to the server. Please check your connection and try again.',
|
||||
)
|
||||
setLoading(false)
|
||||
// Don't rethrow since we're handling the error by setting error state
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@ -107,6 +131,7 @@ function App() {
|
||||
}, [layersApiInstance])
|
||||
|
||||
const getLayers = async () => {
|
||||
try {
|
||||
const layers = await layersApiInstance?.getItems()
|
||||
layers && setLayers(layers)
|
||||
setLayerPageRoutes(
|
||||
@ -126,6 +151,20 @@ function App() {
|
||||
name: l.name, // name that appear in Sidebar
|
||||
})),
|
||||
)
|
||||
// eslint-disable-next-line no-catch-all/no-catch-all
|
||||
} catch (error: any) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Failed to load layers:', error)
|
||||
setError(
|
||||
typeof error === 'string'
|
||||
? error
|
||||
: error?.errors?.[0]?.message ||
|
||||
error?.message ||
|
||||
'Failed to load map layers. Please check your permissions and try again.',
|
||||
)
|
||||
setLoading(false)
|
||||
// Don't rethrow since we're handling the error by setting error state
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@ -140,8 +179,11 @@ function App() {
|
||||
link.href = map?.logo && config.apiUrl + 'assets/' + map.logo // Specify the path to your favicon
|
||||
}
|
||||
|
||||
// Only set loading to false when both map and layers are successfully loaded
|
||||
if (map && layers) {
|
||||
setLoading(false)
|
||||
}, [map])
|
||||
}
|
||||
}, [map, layers])
|
||||
|
||||
const currentUrl = window.location.href
|
||||
const bottomRoutes = getBottomRoutes(currentUrl)
|
||||
@ -253,6 +295,35 @@ function App() {
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
else if (error)
|
||||
return (
|
||||
<div className='tw:flex tw:items-center tw:justify-center tw:h-screen tw:bg-base-100'>
|
||||
<div className='tw:max-w-md tw:mx-auto tw:p-6 tw:text-center'>
|
||||
<div className='tw:mb-4'>
|
||||
<svg
|
||||
className='tw:w-16 tw:h-16 tw:mx-auto tw:text-error tw:mb-4'
|
||||
fill='none'
|
||||
stroke='currentColor'
|
||||
viewBox='0 0 24 24'
|
||||
>
|
||||
<path
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
strokeWidth={2}
|
||||
d='M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.314 16.5c-.77.833.192 2.5 1.732 2.5z'
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h2 className='tw:text-xl tw:font-semibold tw:text-base-content tw:mb-2'>
|
||||
Connection Error
|
||||
</h2>
|
||||
<p className='tw:text-base-content/70 tw:mb-6'>{error}</p>
|
||||
<button onClick={retryConnection} className='tw:btn tw:btn-primary'>
|
||||
Try Again
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
else
|
||||
return (
|
||||
<div className='outer'>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user