Skip to content

Commit

Permalink
Error handling and notification in upload.
Browse files Browse the repository at this point in the history
  • Loading branch information
soup-bowl committed Nov 26, 2023
1 parent a02c51c commit 861da0c
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 34 deletions.
38 changes: 38 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"libwhatsthis": "^0.1.2",
"notistack": "^3.0.1",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-router-dom": "^6.11.0",
Expand Down
57 changes: 30 additions & 27 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import {
} from './pages';
import { APIContext, ConnectionContext } from './context';
import { APIAgentType, Agent } from 'libwhatsthis';
import { SnackbarProvider } from 'notistack';

const App = () => {
const [connectionState, setConnectionState] = useState(navigator.onLine);

const apiAgent: APIAgentType = new Agent(import.meta.env.VITE_API_URL);

useEffect(() => {
Expand All @@ -32,32 +33,34 @@ const App = () => {
<ErrorBoundary>
<APIContext.Provider value={{ apiAgent }}>
<ConnectionContext.Provider value={{ connectionState }}>
<HashRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="help" element={<HelpPage />} />
<Route path="about" element={<AboutPage />} />
<Route path="inspect" element={<InspectionHome />} />
<Route path="inspect/*" element={<InspectonResultDisplay />} />
<Route path="domain/*" element={<DomainToolsHome />} />
<Route path="colour" element={<ColourPickerPage />} />
<Route path="colour/*" element={<ColourPickerPage />} />
<Route path="color" element={<Navigate replace to="/colour" />} />
<Route path="cron" element={<CronConversionPage />} />
<Route path="cron/*" element={<CronConversionPage />} />
<Route path="time" element={<UnixEpochPage />} />
<Route path="time/*" element={<UnixEpochPage />} />
<Route path="scratchpad" element={<ScratchpadPage />} />
<Route path="convert" element={<StringConversionPage />} />
<Route path="encoder" element={<Navigate replace to="/convert" />} />
<Route path="decoder" element={<Navigate replace to="/convert" />} />
<Route path="unix" element={<Navigate replace to="/time" />} />
<Route path="dns/*" element={<Navigate replace to="/domain" />} />
<Route path="*" element={<Navigate replace to="/" />} />
</Route>
</Routes>
</HashRouter>
<SnackbarProvider maxSnack={3}>
<HashRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="help" element={<HelpPage />} />
<Route path="about" element={<AboutPage />} />
<Route path="inspect" element={<InspectionHome />} />
<Route path="inspect/*" element={<InspectonResultDisplay />} />
<Route path="domain/*" element={<DomainToolsHome />} />
<Route path="colour" element={<ColourPickerPage />} />
<Route path="colour/*" element={<ColourPickerPage />} />
<Route path="color" element={<Navigate replace to="/colour" />} />
<Route path="cron" element={<CronConversionPage />} />
<Route path="cron/*" element={<CronConversionPage />} />
<Route path="time" element={<UnixEpochPage />} />
<Route path="time/*" element={<UnixEpochPage />} />
<Route path="scratchpad" element={<ScratchpadPage />} />
<Route path="convert" element={<StringConversionPage />} />
<Route path="encoder" element={<Navigate replace to="/convert" />} />
<Route path="decoder" element={<Navigate replace to="/convert" />} />
<Route path="unix" element={<Navigate replace to="/time" />} />
<Route path="dns/*" element={<Navigate replace to="/domain" />} />
<Route path="*" element={<Navigate replace to="/" />} />
</Route>
</Routes>
</HashRouter>
</SnackbarProvider>
</ConnectionContext.Provider>
</APIContext.Provider>
</ErrorBoundary>
Expand Down
9 changes: 9 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,12 @@ export interface IScratchpadItem {
message: string;
image?: string;
}

export interface IPossibleScratchpadItem {
id?: string;
created?: number;
title?: string;
type?: ScratchpadItemType;
message?: string;
image?: string;
}
26 changes: 20 additions & 6 deletions src/pages/scratchpad.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useEffect, useState } from "react";
import { Alert, AlertTitle, Box, Button, ListItemIcon, ListItemText, Menu, MenuItem, Stack, Typography } from "@mui/material";
import { useSnackbar } from 'notistack';
import { Scratches } from "../components";
import { ScratchEditorModal } from "../modals";
import { addScratch, createItem, getScratches, removeScratch, saveScratches, updateScratch } from "../utils/scratch";
import { IScratchpadItem } from "../interfaces";
import { addScratch, createItem, createItemViaPossible, getScratches, removeScratch, saveScratches, updateScratch } from "../utils/scratch";
import { IPossibleScratchpadItem, IScratchpadItem } from "../interfaces";

import AddIcon from '@mui/icons-material/Add';
import MoreVertIcon from '@mui/icons-material/MoreVert';
Expand All @@ -16,6 +17,7 @@ const ScratchpadPage = () => {
const [openNewNote, setOpenNewNote] = useState(false);
const [menuAnchorEl, setMenuAnchorEl] = useState<null | HTMLElement>(null);
const openMenuDialog = Boolean(menuAnchorEl);
const { enqueueSnackbar } = useSnackbar();

useEffect(() => { document.title = `${siteTitle} - What's This?` });

Expand Down Expand Up @@ -67,11 +69,23 @@ const ScratchpadPage = () => {
reader.onload = (e) => {
const text = (e.target?.result || "") as string;
try {
const data = JSON.parse(text) as IScratchpadItem[];
saveScratches(data);
setScratches(getScratches());
const data = JSON.parse(text) as IPossibleScratchpadItem[];

let collection = getScratches() ?? [];
let count = 0;
data.forEach((item) => {
if (collection.find(exist => exist.id === item.id) === undefined) {
collection?.push(createItemViaPossible(item));
count++;
}
});

saveScratches(collection);
setScratches(collection);
enqueueSnackbar(`Imported ${count.toString()} scratches`);
} catch (error) {
console.error("Error parsing JSON:", error);
console.error("Error parsing file:", error);
enqueueSnackbar("An error occurred processing the import");
} finally {
handleCloseMenu();
}
Expand Down
10 changes: 9 additions & 1 deletion src/utils/scratch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ScratchpadItemType } from "../enums";
import { IScratchpadItem } from "../interfaces";
import { IPossibleScratchpadItem, IScratchpadItem } from "../interfaces";
import { readFromLocalStorage, writeToLocalStorage } from "./localStorage";

export const getScratches = () => readFromLocalStorage<IScratchpadItem[]>('WTScratchpadItems');
Expand Down Expand Up @@ -32,3 +32,11 @@ export const createItem = (title: string, message: string): IScratchpadItem => (
title: title,
message: message,
});

export const createItemViaPossible = (item: IPossibleScratchpadItem):IScratchpadItem => ({
id: item.id ?? self.crypto.randomUUID(),
created: item.created ?? Date.now(),
type: item.type ?? ScratchpadItemType.Text,
title: item.title ?? 'Undefined Title',
message: item.message ?? '',
});

0 comments on commit 861da0c

Please sign in to comment.