Skip to content

Commit 095412e

Browse files
[mod] removes AsyncProvider
- moves loading of exemple image to application component - adds conditional rendering of loading screen - closes #557
1 parent 9d91564 commit 095412e

File tree

9 files changed

+125
-107
lines changed

9 files changed

+125
-107
lines changed

src/components/lists/CategoriesList/CategoriesList.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,12 @@ import { Category } from "store/data/types";
2525
import {
2626
selectActiveCategories,
2727
selectActiveSelectedThingIds,
28-
selectActiveUnknownCategory,
2928
} from "store/project/reselectors";
3029
import { selectClassifierModelStatus } from "store/classifier/selectors";
3130

3231
export const CategoriesList = () => {
3332
const dispatch = useDispatch();
3433
const categories = useSelector(selectActiveCategories);
35-
const activeUnknownCategory = useSelector(selectActiveUnknownCategory);
3634
const activeKind = useSelector(selectActiveKindId);
3735
const [selectedCategory, setSelectedCategory] = useState<Category>();
3836
const [categoryIndex, setCategoryIndex] = useState("");
@@ -201,13 +199,15 @@ export const CategoriesList = () => {
201199
}
202200
/>
203201
</List>
202+
{selectedCategory && (
203+
<CategoryItemMenu
204+
anchorElCategoryMenu={categoryMenuAnchorEl}
205+
category={selectedCategory}
206+
handleCloseCategoryMenu={onCloseCategoryMenu}
207+
openCategoryMenu={Boolean(categoryMenuAnchorEl)}
208+
/>
209+
)}
204210

205-
<CategoryItemMenu
206-
anchorElCategoryMenu={categoryMenuAnchorEl}
207-
category={selectedCategory ?? activeUnknownCategory}
208-
handleCloseCategoryMenu={onCloseCategoryMenu}
209-
openCategoryMenu={Boolean(categoryMenuAnchorEl)}
210-
/>
211211
<CreateCategoryDialog
212212
kind={activeKind}
213213
onClose={handleCloseCreateCategoryDialog}

src/index.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@ import ReactDOM from "react-dom";
33
// import * as serviceWorker from "./serviceWorker";
44

55
import { DndProvider } from "react-dnd";
6+
import { Provider } from "react-redux";
67
import { HTML5Backend } from "react-dnd-html5-backend";
78
import { Application } from "views/Application";
8-
import { AsyncProvider } from "store/AsyncProvider";
9+
import { productionStore } from "store";
910

1011
ReactDOM.render(
11-
<AsyncProvider>
12+
<Provider store={productionStore}>
1213
<DndProvider backend={HTML5Backend}>
1314
<Application />
1415
</DndProvider>
15-
</AsyncProvider>,
16+
</Provider>,
1617
document.getElementById("root")
1718
);
1819

src/store/AsyncProvider.tsx

Lines changed: 0 additions & 81 deletions
This file was deleted.

src/store/data/dataSlice.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { getCompleteEntity, getDeferredProperty } from "store/entities/utils";
66
import { intersection } from "lodash";
77

88
import {
9+
generateUnknownCategory,
910
generateUUID,
1011
isUnknownCategory,
1112
mutatingFilter,
@@ -30,6 +31,7 @@ import {
3031
import { UNKNOWN_CATEGORY_NAME } from "./constants";
3132
import { updateContents } from "./helpers";
3233

34+
const unknownCategory = generateUnknownCategory("Image");
3335
export const kindsAdapter = createDeferredEntityAdapter<Kind>();
3436
export const categoriesAdapter = createDeferredEntityAdapter<Category>();
3537
export const thingsAdapter = createDeferredEntityAdapter<
@@ -38,8 +40,29 @@ export const thingsAdapter = createDeferredEntityAdapter<
3840

3941
export const initialState = (): DataState => {
4042
return {
41-
kinds: kindsAdapter.getInitialState(),
42-
categories: categoriesAdapter.getInitialState(),
43+
kinds: kindsAdapter.getInitialState({
44+
ids: ["Image"],
45+
entities: {
46+
Image: {
47+
saved: {
48+
id: "Image",
49+
containing: [],
50+
categories: [unknownCategory.id],
51+
unknownCategoryId: unknownCategory.id,
52+
},
53+
changes: {},
54+
},
55+
},
56+
}),
57+
categories: categoriesAdapter.getInitialState({
58+
ids: [unknownCategory.id],
59+
entities: {
60+
[unknownCategory.id]: {
61+
saved: unknownCategory,
62+
changes: {},
63+
},
64+
},
65+
}),
4366
things: thingsAdapter.getInitialState(),
4467
};
4568
};

src/store/project/reselectors.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@ export const selectActiveKindObject = createSelector(
3636
export const selectActiveUnknownCategoryId = createSelector(
3737
selectActiveKindObject,
3838
(activeKind) => {
39+
if (!activeKind) return;
3940
return activeKind.unknownCategoryId;
4041
}
4142
);
4243

4344
export const selectActiveCategories = createSelector(
4445
[selectKindDictionary, selectCategoriesDictionary, selectActiveKindId],
4546
(kindDict, categoriesDict, kind) => {
47+
if (!kindDict[kind]) return [];
4648
const categoriesOfKind = kindDict[kind].categories;
4749

4850
return categoriesOfKind.map((catId) => categoriesDict[catId]);
@@ -60,6 +62,7 @@ export const selectActiveUnknownCategory = createSelector(
6062
selectActiveUnknownCategoryId,
6163
selectCategoriesDictionary,
6264
(unknownCatId, catDict) => {
65+
if (!unknownCatId) return;
6366
return catDict[unknownCatId];
6467
}
6568
);
@@ -113,6 +116,7 @@ export const selectUnfilteredActiveCategoryIds = createSelector(
113116
export const selectActiveThingIds = createSelector(
114117
selectActiveKindObject,
115118
(kind) => {
119+
if (!kind) return [];
116120
return kind.containing;
117121
}
118122
);

src/views/Application/Application.tsx

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,74 @@
1-
import React from "react";
1+
import React, { useCallback, useEffect, useState } from "react";
22
import { BrowserRouter, Routes, Route } from "react-router-dom";
3-
3+
import { useDispatch } from "react-redux";
4+
import { CssBaseline } from "@mui/material";
45
import { StyledEngineProvider, ThemeProvider } from "@mui/material/styles";
56

67
import { usePreferredMuiTheme } from "hooks";
78

89
import { ProjectViewer } from "views/ProjectViewer";
910
import { ImageViewer } from "views/ImageViewer";
1011
import { MeasurementView } from "views/MeasurementView";
12+
import { loadExampleImage } from "utils/file-io/loadExampleImage";
13+
import colorImage from "images/cell-painting.png";
14+
import { cellPaintingAnnotations } from "data/exampleImages";
15+
import { OldAnnotationType, OldCategory, OldImageType } from "store/data/types";
16+
import { dataConverter_v1v2 } from "utils/file-io/converters/dataConverter_v1v2";
17+
import { SerializedFileType } from "utils/file-io/types";
18+
import { dataSlice } from "store/data";
19+
import { LoadingScreen } from "./LoadingScreen";
1120

1221
export const Application = () => {
1322
const theme = usePreferredMuiTheme();
23+
const dispatch = useDispatch();
24+
const [hasLoaded, setHasLoaded] = useState(false);
25+
26+
const loadDataState = useCallback(async () => {
27+
const { image, annotationCategories, annotations } =
28+
(await loadExampleImage(
29+
colorImage,
30+
cellPaintingAnnotations as SerializedFileType,
31+
// imageFile.name points to
32+
// "/static/media/cell-painting.f118ef087853056f08e6.png"
33+
"cell-painting.png"
34+
)) as {
35+
image: OldImageType;
36+
annotationCategories: OldCategory[];
37+
annotations: OldAnnotationType[];
38+
};
39+
40+
const dataState = dataConverter_v1v2({
41+
images: [image],
42+
oldCategories: [],
43+
annotations,
44+
annotationCategories,
45+
});
46+
47+
dispatch(dataSlice.actions.initializeState({ data: dataState }));
48+
setHasLoaded(true);
49+
}, [dispatch]);
50+
51+
useEffect(() => {
52+
if (!hasLoaded) {
53+
loadDataState();
54+
}
55+
}, [loadDataState, hasLoaded]);
1456

1557
return (
1658
<StyledEngineProvider injectFirst>
1759
<ThemeProvider theme={theme}>
18-
<BrowserRouter basename={"/"}>
19-
<Routes>
20-
<Route path="/" element={<ProjectViewer />} />
21-
<Route path="imageviewer" element={<ImageViewer />} />
22-
<Route path="measurements" element={<MeasurementView />} />
23-
</Routes>
24-
</BrowserRouter>
60+
<CssBaseline />
61+
{hasLoaded ? (
62+
<BrowserRouter basename={"/"}>
63+
<Routes>
64+
<Route path="/" element={<ProjectViewer />} />
65+
<Route path="imageviewer" element={<ImageViewer />} />
66+
<Route path="measurements" element={<MeasurementView />} />
67+
</Routes>
68+
</BrowserRouter>
69+
) : (
70+
<LoadingScreen />
71+
)}
2572
</ThemeProvider>
2673
</StyledEngineProvider>
2774
);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Box, Typography } from "@mui/material";
2+
import { Logo } from "components/styled-components/Logo";
3+
4+
export const LoadingScreen = () => {
5+
return (
6+
<Box
7+
sx={{
8+
height: "100vh",
9+
display: "flex",
10+
justifyContent: "center",
11+
alignItems: "center",
12+
}}
13+
>
14+
<Box
15+
sx={{
16+
display: "flex",
17+
flexDirection: "column",
18+
alignItems: "center",
19+
}}
20+
>
21+
<Logo width={250} height={50} />
22+
<Typography pt={1}>Loading initial state...</Typography>
23+
</Box>
24+
</Box>
25+
);
26+
};

src/views/ImageViewer/ImageViewer.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useEffect, useCallback, useState, useRef } from "react";
22
import Konva from "konva";
33
import { useDispatch, useSelector } from "react-redux";
44
import { ErrorBoundary } from "react-error-boundary";
5-
import { AppBar, Box, CssBaseline } from "@mui/material";
5+
import { AppBar, Box } from "@mui/material";
66

77
import { useMobileView, useUpload } from "hooks";
88

@@ -136,7 +136,6 @@ export const ImageViewer = () => {
136136
</AppBar>
137137
)}
138138

139-
<CssBaseline />
140139
{isMobile ? <></> : <ImageViewerDrawer />}
141140

142141
<StageWrapper

src/views/ProjectViewer/ProjectViewer.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect } from "react";
22
import { useDispatch, useSelector } from "react-redux";
33
import { ErrorBoundary } from "react-error-boundary";
44

5-
import { Box, CssBaseline } from "@mui/material";
5+
import { Box } from "@mui/material";
66

77
import {
88
useErrorHandler,
@@ -103,7 +103,6 @@ export const ProjectViewer = () => {
103103
<ErrorBoundary FallbackComponent={FallBackDialog}>
104104
<div tabIndex={-1}>
105105
<Box sx={{ height: "100vh" }}>
106-
<CssBaseline />
107106
<ProjectAppBar />
108107

109108
<ProjectDrawer />

0 commit comments

Comments
 (0)