Skip to content

Commit 2d36ceb

Browse files
Merge branch 'issue/557-initial-page-loading'
2 parents 23509a7 + 095412e commit 2d36ceb

File tree

9 files changed

+128
-115
lines changed

9 files changed

+128
-115
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

3836
const [selectedCategory, setSelectedCategory] = useState<Category>();
@@ -213,13 +211,15 @@ export const CategoriesList = () => {
213211
}
214212
/>
215213
</List>
214+
{selectedCategory && (
215+
<CategoryItemMenu
216+
anchorElCategoryMenu={categoryMenuAnchorEl}
217+
category={selectedCategory}
218+
handleCloseCategoryMenu={onCloseCategoryMenu}
219+
openCategoryMenu={Boolean(categoryMenuAnchorEl)}
220+
/>
221+
)}
216222

217-
<CategoryItemMenu
218-
anchorElCategoryMenu={categoryMenuAnchorEl}
219-
category={selectedCategory ?? activeUnknownCategory}
220-
handleCloseCategoryMenu={onCloseCategoryMenu}
221-
openCategoryMenu={Boolean(categoryMenuAnchorEl)}
222-
/>
223223
<CreateCategoryDialog
224224
kind={activeKind}
225225
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 & 87 deletions
This file was deleted.

src/store/data/dataSlice.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
import { UNKNOWN_CATEGORY_NAME } from "./constants";
3232
import { updateContents } from "./helpers";
3333

34+
const unknownCategory = generateUnknownCategory("Image");
3435
export const kindsAdapter = createDeferredEntityAdapter<Kind>();
3536
export const categoriesAdapter = createDeferredEntityAdapter<Category>();
3637
export const thingsAdapter = createDeferredEntityAdapter<
@@ -39,8 +40,29 @@ export const thingsAdapter = createDeferredEntityAdapter<
3940

4041
export const initialState = (): DataState => {
4142
return {
42-
kinds: kindsAdapter.getInitialState(),
43-
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+
}),
4466
things: thingsAdapter.getInitialState(),
4567
};
4668
};

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: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
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";
@@ -9,22 +10,70 @@ import { ProjectViewer } from "views/ProjectViewer";
910
import { ImageViewer } from "views/ImageViewer";
1011
import { MeasurementView } from "views/MeasurementView";
1112
import { FileUploadProvider } from "contexts";
13+
import { loadExampleImage } from "utils/file-io/loadExampleImage";
14+
import colorImage from "images/cell-painting.png";
15+
import { cellPaintingAnnotations } from "data/exampleImages";
16+
import { OldAnnotationType, OldCategory, OldImageType } from "store/data/types";
17+
import { dataConverter_v1v2 } from "utils/file-io/converters/dataConverter_v1v2";
18+
import { SerializedFileType } from "utils/file-io/types";
19+
import { dataSlice } from "store/data";
20+
import { LoadingScreen } from "./LoadingScreen";
21+
import { projectSlice } from "store/project";
1222

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

1660
return (
1761
<StyledEngineProvider injectFirst>
1862
<ThemeProvider theme={theme}>
19-
<FileUploadProvider>
20-
<BrowserRouter basename={"/"}>
21-
<Routes>
22-
<Route path="/" element={<ProjectViewer />} />
23-
<Route path="imageviewer" element={<ImageViewer />} />
24-
<Route path="measurements" element={<MeasurementView />} />
25-
</Routes>
26-
</BrowserRouter>
27-
</FileUploadProvider>
63+
<CssBaseline />
64+
{hasLoaded ? (
65+
<FileUploadProvider>
66+
<BrowserRouter basename={"/"}>
67+
<Routes>
68+
<Route path="/" element={<ProjectViewer />} />
69+
<Route path="imageviewer" element={<ImageViewer />} />
70+
<Route path="measurements" element={<MeasurementView />} />
71+
</Routes>
72+
</BrowserRouter>
73+
</FileUploadProvider>
74+
) : (
75+
<LoadingScreen />
76+
)}
2877
</ThemeProvider>
2978
</StyledEngineProvider>
3079
);
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 } from "hooks";
88

@@ -119,7 +119,6 @@ export const ImageViewer = () => {
119119
</AppBar>
120120
)}
121121

122-
<CssBaseline />
123122
{isMobile ? <></> : <ImageViewerDrawer />}
124123

125124
<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,
@@ -110,7 +110,6 @@ export const ProjectViewer = () => {
110110
<ErrorBoundary FallbackComponent={FallBackDialog}>
111111
<div tabIndex={-1}>
112112
<Box sx={{ height: "100vh" }}>
113-
<CssBaseline />
114113
<ProjectAppBar />
115114

116115
<ProjectDrawer />

0 commit comments

Comments
 (0)