Skip to content

Commit

Permalink
Merge branch 'issue/557-initial-page-loading'
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrea-Papaleo committed Jul 23, 2024
2 parents 23509a7 + 095412e commit 2d36ceb
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 115 deletions.
16 changes: 8 additions & 8 deletions src/components/lists/CategoriesList/CategoriesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,12 @@ import { Category } from "store/data/types";
import {
selectActiveCategories,
selectActiveSelectedThingIds,
selectActiveUnknownCategory,
} from "store/project/reselectors";
import { selectClassifierModelStatus } from "store/classifier/selectors";

export const CategoriesList = () => {
const dispatch = useDispatch();
const categories = useSelector(selectActiveCategories);
const activeUnknownCategory = useSelector(selectActiveUnknownCategory);
const activeKind = useSelector(selectActiveKindId);

const [selectedCategory, setSelectedCategory] = useState<Category>();
Expand Down Expand Up @@ -213,13 +211,15 @@ export const CategoriesList = () => {
}
/>
</List>
{selectedCategory && (
<CategoryItemMenu
anchorElCategoryMenu={categoryMenuAnchorEl}
category={selectedCategory}
handleCloseCategoryMenu={onCloseCategoryMenu}
openCategoryMenu={Boolean(categoryMenuAnchorEl)}
/>
)}

<CategoryItemMenu
anchorElCategoryMenu={categoryMenuAnchorEl}
category={selectedCategory ?? activeUnknownCategory}
handleCloseCategoryMenu={onCloseCategoryMenu}
openCategoryMenu={Boolean(categoryMenuAnchorEl)}
/>
<CreateCategoryDialog
kind={activeKind}
onClose={handleCloseCreateCategoryDialog}
Expand Down
7 changes: 4 additions & 3 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ import ReactDOM from "react-dom";
// import * as serviceWorker from "./serviceWorker";

import { DndProvider } from "react-dnd";
import { Provider } from "react-redux";
import { HTML5Backend } from "react-dnd-html5-backend";
import { Application } from "views/Application";
import { AsyncProvider } from "store/AsyncProvider";
import { productionStore } from "store";

ReactDOM.render(
<AsyncProvider>
<Provider store={productionStore}>
<DndProvider backend={HTML5Backend}>
<Application />
</DndProvider>
</AsyncProvider>,
</Provider>,
document.getElementById("root")
);

Expand Down
87 changes: 0 additions & 87 deletions src/store/AsyncProvider.tsx

This file was deleted.

26 changes: 24 additions & 2 deletions src/store/data/dataSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
import { UNKNOWN_CATEGORY_NAME } from "./constants";
import { updateContents } from "./helpers";

const unknownCategory = generateUnknownCategory("Image");
export const kindsAdapter = createDeferredEntityAdapter<Kind>();
export const categoriesAdapter = createDeferredEntityAdapter<Category>();
export const thingsAdapter = createDeferredEntityAdapter<
Expand All @@ -39,8 +40,29 @@ export const thingsAdapter = createDeferredEntityAdapter<

export const initialState = (): DataState => {
return {
kinds: kindsAdapter.getInitialState(),
categories: categoriesAdapter.getInitialState(),
kinds: kindsAdapter.getInitialState({
ids: ["Image"],
entities: {
Image: {
saved: {
id: "Image",
containing: [],
categories: [unknownCategory.id],
unknownCategoryId: unknownCategory.id,
},
changes: {},
},
},
}),
categories: categoriesAdapter.getInitialState({
ids: [unknownCategory.id],
entities: {
[unknownCategory.id]: {
saved: unknownCategory,
changes: {},
},
},
}),
things: thingsAdapter.getInitialState(),
};
};
Expand Down
4 changes: 4 additions & 0 deletions src/store/project/reselectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ export const selectActiveKindObject = createSelector(
export const selectActiveUnknownCategoryId = createSelector(
selectActiveKindObject,
(activeKind) => {
if (!activeKind) return;
return activeKind.unknownCategoryId;
}
);

export const selectActiveCategories = createSelector(
[selectKindDictionary, selectCategoriesDictionary, selectActiveKindId],
(kindDict, categoriesDict, kind) => {
if (!kindDict[kind]) return [];
const categoriesOfKind = kindDict[kind].categories;

return categoriesOfKind.map((catId) => categoriesDict[catId]);
Expand All @@ -60,6 +62,7 @@ export const selectActiveUnknownCategory = createSelector(
selectActiveUnknownCategoryId,
selectCategoriesDictionary,
(unknownCatId, catDict) => {
if (!unknownCatId) return;
return catDict[unknownCatId];
}
);
Expand Down Expand Up @@ -113,6 +116,7 @@ export const selectUnfilteredActiveCategoryIds = createSelector(
export const selectActiveThingIds = createSelector(
selectActiveKindObject,
(kind) => {
if (!kind) return [];
return kind.containing;
}
);
Expand Down
71 changes: 60 additions & 11 deletions src/views/Application/Application.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import React, { useCallback, useEffect, useState } from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";

import { useDispatch } from "react-redux";
import { CssBaseline } from "@mui/material";
import { StyledEngineProvider, ThemeProvider } from "@mui/material/styles";

import { usePreferredMuiTheme } from "hooks";
Expand All @@ -9,22 +10,70 @@ import { ProjectViewer } from "views/ProjectViewer";
import { ImageViewer } from "views/ImageViewer";
import { MeasurementView } from "views/MeasurementView";
import { FileUploadProvider } from "contexts";
import { loadExampleImage } from "utils/file-io/loadExampleImage";
import colorImage from "images/cell-painting.png";
import { cellPaintingAnnotations } from "data/exampleImages";
import { OldAnnotationType, OldCategory, OldImageType } from "store/data/types";
import { dataConverter_v1v2 } from "utils/file-io/converters/dataConverter_v1v2";
import { SerializedFileType } from "utils/file-io/types";
import { dataSlice } from "store/data";
import { LoadingScreen } from "./LoadingScreen";
import { projectSlice } from "store/project";

export const Application = () => {
const theme = usePreferredMuiTheme();
const dispatch = useDispatch();
const [hasLoaded, setHasLoaded] = useState(false);

const loadDataState = useCallback(async () => {
const { image, annotationCategories, annotations } =
(await loadExampleImage(
colorImage,
cellPaintingAnnotations as SerializedFileType,
// imageFile.name points to
// "/static/media/cell-painting.f118ef087853056f08e6.png"
"cell-painting.png"
)) as {
image: OldImageType;
annotationCategories: OldCategory[];
annotations: OldAnnotationType[];
};

const dataState = dataConverter_v1v2({
images: [image],
oldCategories: [],
annotations,
annotationCategories,
});

dispatch(dataSlice.actions.initializeState({ data: dataState }));
dispatch(projectSlice.actions.setProjectImageChannels({ channels: 3 }));
setHasLoaded(true);
}, [dispatch]);

useEffect(() => {
if (!hasLoaded) {
loadDataState();
}
}, [loadDataState, hasLoaded]);

return (
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<FileUploadProvider>
<BrowserRouter basename={"/"}>
<Routes>
<Route path="/" element={<ProjectViewer />} />
<Route path="imageviewer" element={<ImageViewer />} />
<Route path="measurements" element={<MeasurementView />} />
</Routes>
</BrowserRouter>
</FileUploadProvider>
<CssBaseline />
{hasLoaded ? (
<FileUploadProvider>
<BrowserRouter basename={"/"}>
<Routes>
<Route path="/" element={<ProjectViewer />} />
<Route path="imageviewer" element={<ImageViewer />} />
<Route path="measurements" element={<MeasurementView />} />
</Routes>
</BrowserRouter>
</FileUploadProvider>
) : (
<LoadingScreen />
)}
</ThemeProvider>
</StyledEngineProvider>
);
Expand Down
26 changes: 26 additions & 0 deletions src/views/Application/LoadingScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Box, Typography } from "@mui/material";
import { Logo } from "components/styled-components/Logo";

export const LoadingScreen = () => {
return (
<Box
sx={{
height: "100vh",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<Logo width={250} height={50} />
<Typography pt={1}>Loading initial state...</Typography>
</Box>
</Box>
);
};
3 changes: 1 addition & 2 deletions src/views/ImageViewer/ImageViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useEffect, useCallback, useState, useRef } from "react";
import Konva from "konva";
import { useDispatch, useSelector } from "react-redux";
import { ErrorBoundary } from "react-error-boundary";
import { AppBar, Box, CssBaseline } from "@mui/material";
import { AppBar, Box } from "@mui/material";

import { useMobileView } from "hooks";

Expand Down Expand Up @@ -119,7 +119,6 @@ export const ImageViewer = () => {
</AppBar>
)}

<CssBaseline />
{isMobile ? <></> : <ImageViewerDrawer />}

<StageWrapper
Expand Down
3 changes: 1 addition & 2 deletions src/views/ProjectViewer/ProjectViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useCallback, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { ErrorBoundary } from "react-error-boundary";

import { Box, CssBaseline } from "@mui/material";
import { Box } from "@mui/material";

import {
useErrorHandler,
Expand Down Expand Up @@ -110,7 +110,6 @@ export const ProjectViewer = () => {
<ErrorBoundary FallbackComponent={FallBackDialog}>
<div tabIndex={-1}>
<Box sx={{ height: "100vh" }}>
<CssBaseline />
<ProjectAppBar />

<ProjectDrawer />
Expand Down

0 comments on commit 2d36ceb

Please sign in to comment.