Skip to content

Commit

Permalink
Merge pull request #420 from Renumics/feature/special-view-for-errors…
Browse files Browse the repository at this point in the history
…-on-load

Feature/special view for errors on load
  • Loading branch information
neindochoh authored Feb 13, 2024
2 parents 25c7d86 + cc2c25a commit 581e393
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 41 deletions.
9 changes: 6 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,20 @@ import tw from 'twin.macro';
import 'styled-components';
import usePluginStore from './stores/pluginStore';
import DragContext from './systems/dnd/DragContext';
import LoadingError from './components/LoadingError';

const Wrapper = tw.div`bg-gray-200 text-midnight-600 w-screen h-screen relative overflow-hidden`;
const Wrapper = tw.main`bg-gray-200 text-midnight-600 w-screen h-screen relative overflow-hidden`;

// fetch the dataset once on app init
useDataset.getState().fetch();

const loadingSelector = (d: Dataset) => d.loading;
const loadingErrorSelector = (d: Dataset) => d.loadingError;

const App = (): JSX.Element => {
const plugins = usePluginStore((state) => state.plugins);

const loading = useDataset(loadingSelector) || plugins === undefined;
const loadingError = useDataset(loadingErrorSelector);

const workspace = useRef<WorkspaceHandle>(null);
const resetWorkspace = () => workspace.current?.reset();
Expand All @@ -44,7 +46,7 @@ const App = (): JSX.Element => {
<DragContext>
<Wrapper>
<WebGLDetector />
{!loading && (
{!loading && !loadingError && (
<ContextMenuProvider>
<div tw="flex flex-col h-full w-full">
<div tw="flex-initial relative">
Expand Down Expand Up @@ -72,6 +74,7 @@ const App = (): JSX.Element => {
<LoadingIndicator />
</div>
)}
{loadingError && <LoadingError problem={loadingError} />}
<ToastContainer position="bottom-right" />
</Wrapper>
</DragContext>
Expand Down
19 changes: 19 additions & 0 deletions src/api/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Problem } from '../types';

const DEFAULT_PROBLEM: Problem = {
type: 'UndefinedApiError',
title: 'Undefined API Error',
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export async function parseError(error: any): Promise<Problem> {
if (!error.response?.json) {
return DEFAULT_PROBLEM;
}

try {
return (await error.response.json()) as Problem;
} catch {
return DEFAULT_PROBLEM;
}
}
2 changes: 2 additions & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import application from '../application';
import { FilebrowserApi, LayoutApi, PluginsApi, TableApi, IssuesApi } from '../client';
import { Configuration } from '../client/runtime';
import { parseError } from './errors';

const config = new Configuration({ basePath: application.apiUrl });

Expand All @@ -10,4 +11,5 @@ export default {
layout: new LayoutApi(config),
plugin: new PluginsApi(config),
issues: new IssuesApi(config),
parseError,
};
39 changes: 39 additions & 0 deletions src/components/LoadingError.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import application from '../application';
import { useDataset } from '../lib';
import { Problem } from '../types';
import Center from './ui/Center';
import tw from 'twin.macro';

interface Props {
problem: Problem;
}

const Button = tw.button`border border-gray-600 rounded px-2 py-1 text-sm`;

const LoadingError = ({ problem }: Props): JSX.Element => {
const reload = () => location.reload();
const browse = () => useDataset.getState().clearLoadingError();
const close = () => window.close();

return (
<Center tw="flex flex-col gap-y-4 text-midnight-600">
<div tw="flex flex-col items-center">
<h1 tw="text-lg">Failed to load your dataset</h1>
<p tw="text-sm text-gray-800">(with the following API error)</p>
</div>
<div tw="border border-red-600 rounded bg-red-100 divide-y divide-red-600">
<h2 tw="font-bold p-1">{problem.title}</h2>
{problem.detail && <p tw="p-1 text-sm">{problem.detail}</p>}
</div>
<div tw="flex flex-row gap-x-2">
<Button onClick={reload}>Reload</Button>
{application.filebrowsingAllowed && (
<Button onClick={browse}>Open another dataset</Button>
)}
<Button onClick={close}>Close</Button>
</div>
</Center>
);
};

export default LoadingError;
5 changes: 5 additions & 0 deletions src/components/ui/Center.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import tw from 'twin.macro';

const Center = tw.div`w-full h-full flex justify-center items-center`;

export default Center;
71 changes: 33 additions & 38 deletions src/stores/dataset/dataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { useColors } from '../colors';
import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware';
import { shallow } from 'zustand/shallow';
import { Table } from '../../client';
import {
ColumnsStats,
DataColumn,
Expand All @@ -16,6 +15,7 @@ import {
Filter,
IndexArray,
TableData,
Problem,
} from '../../types';
import api from '../../api';
import { notifyAPIError, notifyError } from '../../notify';
Expand All @@ -34,6 +34,7 @@ export interface Dataset {
generationID: number;
filename?: string; // filename of the dataset
loading: boolean; // are we currently loading the Dataset
loadingError?: Problem;
columnStats: { full: ColumnsStats; selected: ColumnsStats; filtered: ColumnsStats }; // an object storing statistics for available columns
columns: DataColumn[];
columnsByKey: Record<string, DataColumn>;
Expand Down Expand Up @@ -85,6 +86,7 @@ export interface Dataset {
isComputingRelevance: boolean;
recomputeColumnRelevance: () => void;
focusRow: (row?: number) => void;
clearLoadingError: () => void;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -114,24 +116,7 @@ const fetchTable = async (): Promise<{
filename: string;
dataframe: DataFrame;
}> => {
let table: Table;

try {
table = await api.table.getTable();
} catch (error) {
notifyAPIError(error);
return {
uid: '',
generationID: -1,
filename: '',
dataframe: {
columns: [],
length: 0,
data: {},
},
};
}

const table = await api.table.getTable();
const columns = table.columns.map(makeColumn);
const columnData: TableData = {};
table.columns.forEach((rawColumn, i) => {
Expand Down Expand Up @@ -234,27 +219,34 @@ export const useDataset = create(
rowsWithIssues: [],
isAnalysisRunning: true,
}));
try {
const { uid, generationID, filename, dataframe } =
await fetchTable();

const tableFetcher = fetchTable();
const { uid, generationID, filename, dataframe } = await tableFetcher;

const columnStats = {
full: makeColumnsStats(dataframe.columns, dataframe.data),
selected: {},
filtered: {},
};
const columnStats = {
full: makeColumnsStats(dataframe.columns, dataframe.data),
selected: {},
filtered: {},
};

set({
uid,
generationID,
filename,
length: dataframe.length,
loading: false,
columns: dataframe.columns,
columnsByKey: _.keyBy(dataframe.columns, 'key'),
columnData: dataframe.data,
columnStats,
});
set({
uid,
generationID,
filename,
length: dataframe.length,
loading: false,
columns: dataframe.columns,
columnsByKey: _.keyBy(dataframe.columns, 'key'),
columnData: dataframe.data,
columnStats,
});
} catch (error) {
const problem = await api.parseError(error);
set({
loading: false,
loadingError: problem,
});
}
},
refetchColumnValues: async (columnKey) => {
const column = get().columnsByKey[columnKey];
Expand Down Expand Up @@ -480,6 +472,9 @@ export const useDataset = create(
colorTransferFunctions: newTransferFunctions,
});
},
clearLoadingError: () => {
set({ loadingError: undefined });
},
};
})
);
Expand Down

0 comments on commit 581e393

Please sign in to comment.