Warn on invalid JSON file (#1159)

* add error dialog

* show error modal on file dnd

* add locales

* Update src/locales/en.json

Co-Authored-By: Lipis <lipiridis@gmail.com>

* Update src/data/blob.ts

* Update src/data/blob.ts

* fix titles, update snapshots

* make modal smaller

* fix dnd wrong file type

* reset errorMessage

Co-authored-by: Faustino Kialungila <faustino.kialungila@gmail.com>
Co-authored-by: Lipis <lipiridis@gmail.com>
This commit is contained in:
Kostas Bariotis 2020-04-03 12:50:51 +01:00 committed by GitHub
parent 2be34effd4
commit 0c9459e9e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 108 additions and 7 deletions

View File

@ -64,11 +64,14 @@ export const actionLoadScene = register({
perform: (
elements,
appState,
{ elements: loadedElements, appState: loadedAppState },
{ elements: loadedElements, appState: loadedAppState, error },
) => {
return {
elements: loadedElements,
appState: loadedAppState,
appState: {
...loadedAppState,
errorMessage: error,
},
commitToHistory: false,
};
},
@ -84,7 +87,9 @@ export const actionLoadScene = register({
.then(({ elements, appState }) => {
updateData({ elements: elements, appState: appState });
})
.catch((error) => console.error(error));
.catch((error) => {
updateData({ error: error });
});
}}
/>
),

View File

@ -6,6 +6,7 @@ export const DEFAULT_FONT = "20px Virgil";
export function getDefaultAppState(): AppState {
return {
isLoading: false,
errorMessage: null,
draggingElement: null,
resizingElement: null,
multiElement: null,
@ -52,6 +53,7 @@ export function clearAppStateForLocalStorage(appState: AppState) {
collaborators,
isCollaborating,
isLoading,
errorMessage,
...exportedState
} = appState;
return exportedState;

View File

@ -247,9 +247,13 @@ export class App extends React.Component<any, AppState> {
}),
)
.catch((error) => {
console.error(error);
this.setState({ isLoading: false });
this.setState({ isLoading: false, errorMessage: error });
});
} else {
this.setState({
isLoading: false,
errorMessage: t("alerts.couldNotLoadInvalidFile"),
});
}
}}
>

View File

@ -0,0 +1,36 @@
import React, { useState } from "react";
import { t } from "../i18n";
import { Dialog } from "./Dialog";
export function ErrorDialog({
message,
onClose,
}: {
message: string;
onClose?: () => void;
}) {
const [modalIsShown, setModalIsShown] = useState(!!message);
const handleClose = React.useCallback(() => {
setModalIsShown(false);
if (onClose) {
onClose();
}
}, [onClose]);
return (
<>
{modalIsShown && (
<Dialog
maxWidth={500}
onCloseRequest={handleClose}
title={t("errorDialog.title")}
>
<div>{message}</div>
</Dialog>
)}
</>
);
}

View File

@ -22,6 +22,7 @@ import { MobileMenu } from "./MobileMenu";
import { ZoomActions, SelectedShapeActions, ShapesSwitcher } from "./Actions";
import { Section } from "./Section";
import { RoomDialog } from "./RoomDialog";
import { ErrorDialog } from "./ErrorDialog";
import { LoadingMessage } from "./LoadingMessage";
interface LayerUIProps {
@ -105,6 +106,12 @@ export const LayerUI = React.memo(
) : (
<>
{appState.isLoading && <LoadingMessage />}
{appState.errorMessage && (
<ErrorDialog
message={appState.errorMessage}
onClose={() => setAppState({ errorMessage: null })}
/>
)}
<FixedSideContainer side="top">
<HintViewer appState={appState} elements={elements} />
<div className="App-menu App-menu_top">

View File

@ -1,6 +1,7 @@
import { getDefaultAppState } from "../appState";
import { DataState } from "./types";
import { restore } from "./restore";
import { t } from "../i18n";
export async function loadFromBlob(blob: any) {
const updateAppState = (contents: string) => {
@ -10,7 +11,7 @@ export async function loadFromBlob(blob: any) {
try {
const data = JSON.parse(contents);
if (data.type !== "excalidraw") {
throw new Error("Cannot load invalid json");
throw new Error(t("alerts.couldNotLoadInvalidFile"));
}
elements = data.elements || [];
appState = { ...defaultAppState, ...data.appState };
@ -39,7 +40,7 @@ export async function loadFromBlob(blob: any) {
}
const { elements, appState } = updateAppState(contents);
if (!elements.length) {
return Promise.reject("Cannot load invalid json");
return Promise.reject(t("alerts.couldNotLoadInvalidFile"));
}
return new Promise<DataState>((resolve) => {
resolve(restore(elements, appState, { scrollToContent: true }));

View File

@ -74,6 +74,7 @@
"alerts": {
"clearReset": "This will clear the whole canvas. Are you sure?",
"couldNotCreateShareableLink": "Couldn't create shareable link.",
"couldNotLoadInvalidFile": "Couldn't load invalid file",
"importBackendFailed": "Importing from backend failed.",
"cannotExportEmptyCanvas": "Cannot export empty canvas.",
"couldNotCopyToClipboard": "Couldn't copy to clipboard. Try using Chrome browser.",
@ -123,5 +124,8 @@
"desc_persistenceWarning": "Note that the scene data is shared across collaborators in a P2P fashion, and not persisted to our server. Thus, if all of you disconnect, you will loose the data unless you export it to a file or a shareable link.",
"desc_shareLink": "Share this link with anyone you want to collaborate with:",
"desc_exitSession": "Stopping the session will disconnect your from the room, but you'll be able to continue working with the scene, locally. Note that this won't affect other people, and they'll still be able to collaborate on their version."
},
"errorDialog": {
"title": "Error"
}
}

View File

@ -16,6 +16,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -202,6 +203,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -311,6 +313,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -560,6 +563,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -705,6 +709,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -886,6 +891,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -1072,6 +1078,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -1354,6 +1361,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -1949,6 +1957,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -2058,6 +2067,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -2167,6 +2177,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -2276,6 +2287,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -2407,6 +2419,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -2538,6 +2551,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -2669,6 +2683,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -2778,6 +2793,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -2887,6 +2903,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -3018,6 +3035,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -3127,6 +3145,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -3178,6 +3197,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -3863,6 +3883,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -4224,6 +4245,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -4513,6 +4535,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -4730,6 +4753,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -4875,6 +4899,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -5524,6 +5549,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -6101,6 +6127,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -6606,6 +6633,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -7039,6 +7067,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -7436,6 +7465,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -7761,6 +7791,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -8014,6 +8045,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -8195,6 +8227,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -8880,6 +8913,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -9493,6 +9527,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -10034,6 +10069,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -10503,6 +10539,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -10746,6 +10783,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -10795,6 +10833,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -10846,6 +10885,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,
@ -11127,6 +11167,7 @@ Object {
"editingElement": null,
"elementLocked": false,
"elementType": "selection",
"errorMessage": null,
"exportBackground": true,
"isCollaborating": false,
"isLoading": false,

View File

@ -11,6 +11,7 @@ export type Point = Readonly<RoughPoint>;
export type AppState = {
isLoading: boolean;
errorMessage: string | null;
draggingElement: ExcalidrawElement | null;
resizingElement: ExcalidrawElement | null;
multiElement: ExcalidrawLinearElement | null;