From 0d8d3a4851d731e4db868d265224b5b9f3685882 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 27 Jun 2023 11:58:10 +0100 Subject: [PATCH] Handle showing errors inside grids --- .../src/components/grid/layout/Grid.svelte | 29 ++++++++++++++++++- .../src/components/grid/stores/rows.js | 15 +++++++++- packages/frontend-core/src/fetch/DataFetch.js | 5 ++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/packages/frontend-core/src/components/grid/layout/Grid.svelte b/packages/frontend-core/src/components/grid/layout/Grid.svelte index e94cf5da93..5207f293b1 100644 --- a/packages/frontend-core/src/components/grid/layout/Grid.svelte +++ b/packages/frontend-core/src/components/grid/layout/Grid.svelte @@ -68,6 +68,7 @@ rowHeight, contentLines, gridFocused, + error, } = context // Keep config store up to date with props @@ -149,8 +150,15 @@ + {:else if $error} +
+
There was a problem loading your grid
+
+ {$error} +
+
{/if} - {#if $loading} + {#if $loading && !$error}
@@ -273,6 +281,25 @@ opacity: 0.6; } + /* Error */ + .grid-error { + position: absolute; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 8px; + } + .grid-error-title { + font-size: 18px; + font-weight: 600; + } + .grid-error-subtitle { + font-size: 16px; + } + /* Disable checkbox animation anywhere in the grid data */ .grid-data-outer :global(.spectrum-Checkbox-box:before), .grid-data-outer :global(.spectrum-Checkbox-box:after), diff --git a/packages/frontend-core/src/components/grid/stores/rows.js b/packages/frontend-core/src/components/grid/stores/rows.js index 1a98ef1848..d348d5caa5 100644 --- a/packages/frontend-core/src/components/grid/stores/rows.js +++ b/packages/frontend-core/src/components/grid/stores/rows.js @@ -14,6 +14,7 @@ export const createStores = () => { const rowChangeCache = writable({}) const inProgressChanges = writable({}) const hasNextPage = writable(false) + const error = writable(null) // Generate a lookup map to quick find a row by ID const rowLookupMap = derived( @@ -47,6 +48,7 @@ export const createStores = () => { rowChangeCache, inProgressChanges, hasNextPage, + error, } } @@ -68,6 +70,7 @@ export const deriveStores = context => { inProgressChanges, previousFocusedRowId, hasNextPage, + error, } = context const instanceLoaded = writable(false) const fetch = writable(null) @@ -122,7 +125,17 @@ export const deriveStores = context => { // Subscribe to changes of this fetch model unsubscribe = newFetch.subscribe(async $fetch => { - if ($fetch.loaded && !$fetch.loading) { + if ($fetch.error) { + // Present a helpful error to the user + let message = "An unknown error occurred" + if ($fetch.error.status === 403) { + message = "You don't have access to this data" + } else if ($fetch.error.message) { + message = $fetch.error.message + } + error.set(message) + } else if ($fetch.loaded && !$fetch.loading) { + error.set(null) hasNextPage.set($fetch.hasNextPage) const $instanceLoaded = get(instanceLoaded) const resetRows = $fetch.resetKey !== lastResetKey diff --git a/packages/frontend-core/src/fetch/DataFetch.js b/packages/frontend-core/src/fetch/DataFetch.js index b456753d4a..f9d7fd2624 100644 --- a/packages/frontend-core/src/fetch/DataFetch.js +++ b/packages/frontend-core/src/fetch/DataFetch.js @@ -57,6 +57,7 @@ export default class DataFetch { cursor: null, cursors: [], resetKey: Math.random(), + error: null, }) // Merge options with their default values @@ -252,6 +253,10 @@ export default class DataFetch { try { return await this.API.fetchTableDefinition(datasource.tableId) } catch (error) { + this.store.update(state => ({ + ...state, + error, + })) return null } }