diff --git a/src/App.tsx b/src/App.tsx
index c330ada3..a9ebbee9 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -6,6 +6,7 @@ import { getFirebaseRecipe, jsonToString } from "./utils/recipeLoader";
import { getSubmitPackingUrl, JOB_STATUS } from "./constants/aws";
import { FIRESTORE_FIELDS } from "./constants/firebase";
import {
+ useCurrentRecipeData,
useJobId,
useJobLogs,
useOutputsDirectory,
@@ -33,6 +34,7 @@ function App() {
const setPackingResults = useSetPackingResults();
const runTime = useRunTime();
const outputDir = useOutputsDirectory();
+ const edits = useCurrentRecipeData()?.edits || {};
let start = 0;
@@ -144,6 +146,7 @@ function App() {
resultUrl: localJobStatus.result_path,
runTime: range,
outputDir: localJobStatus.outputs_directory,
+ edits: edits,
});
} else if (localJobStatus.status == JOB_STATUS.FAILED) {
setPackingResults({
@@ -152,6 +155,7 @@ function App() {
resultUrl: "",
runTime: range,
outputDir: "",
+ edits: {}
});
}
};
diff --git a/src/components/PackingInput/index.tsx b/src/components/PackingInput/index.tsx
index a2de51da..6ed61bd6 100644
--- a/src/components/PackingInput/index.tsx
+++ b/src/components/PackingInput/index.tsx
@@ -9,6 +9,7 @@ import {
useCurrentRecipeObject,
useInputOptions,
useLoadInputOptions,
+ useIsLoading,
} from "../../state/store";
import Dropdown from "../Dropdown";
import JSONViewer from "../JSONViewer";
@@ -36,6 +37,7 @@ const PackingInput = (props: PackingInputProps): JSX.Element => {
const selectedRecipeId = useSelectedRecipeId();
const recipeObj = useCurrentRecipeObject();
const inputOptions = useInputOptions();
+ const isLoading = useIsLoading();
const loadInputOptions = useLoadInputOptions();
const loadAllRecipes = useLoadAllRecipes();
@@ -73,7 +75,7 @@ const PackingInput = (props: PackingInputProps): JSX.Element => {
const loadingText =
Loading...
;
// No recipe or dropdown options to load
- if (!recipeObj && !inputOptions[selectedRecipeId]) {
+ if (isLoading) {
return loadingText;
}
diff --git a/src/components/Viewer/index.tsx b/src/components/Viewer/index.tsx
index 8a2dc79d..1a36e48e 100644
--- a/src/components/Viewer/index.tsx
+++ b/src/components/Viewer/index.tsx
@@ -1,15 +1,43 @@
+import { LoadingOutlined } from "@ant-design/icons";
import { SIMULARIUM_EMBED_URL } from "../../constants/urls";
-import { useResultUrl } from "../../state/store";
+import { useIsLoading, useIsModified, useIsPacking, useResultUrl } from "../../state/store";
import "./style.css";
const Viewer = (): JSX.Element => {
const resultUrl = useResultUrl();
+ const isLoading = useIsLoading();
+ const isPacking = useIsPacking();
+ const isModified = useIsModified();
+
+ const overlayText = isPacking
+ ? "Running..."
+ : isLoading
+ ? "Loading..."
+ : isModified
+ ? "Re-run packing to view result"
+ : "";
+
+ const activeState = isLoading || isPacking;
+ const showOverlay = activeState || isModified;
+
return (
+ {showOverlay && (
+
+
+ {activeState &&
}
+
{overlayText}
+
+
+ )}
);
};
diff --git a/src/components/Viewer/style.css b/src/components/Viewer/style.css
index 25ca27d7..479292df 100644
--- a/src/components/Viewer/style.css
+++ b/src/components/Viewer/style.css
@@ -1,6 +1,7 @@
.viewer-container {
width: 100%;
height: 100%;
+ position: relative;
}
.simularium-embed {
@@ -8,3 +9,34 @@
height: 100%;
border: 1px solid black;
}
+
+.viewer-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: #DCDDE5;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 10;
+}
+
+.overlay-content {
+ color: #989898;
+ font-size: 32px;
+ text-align: center;
+}
+
+.overlay-content.active {
+ color: #468ADE;
+}
+
+.dark-theme .viewer-overlay {
+ background-color: #2C2F38;
+}
+
+.dark-theme .overlay-content.active {
+ color: #8b91ff;
+}
diff --git a/src/state/constants.ts b/src/state/constants.ts
index 46418079..9bb1fec3 100644
--- a/src/state/constants.ts
+++ b/src/state/constants.ts
@@ -8,4 +8,5 @@ export const EMPTY_PACKING_RESULT: PackingResult = Object.freeze({
resultUrl: "",
runTime: 0,
outputDir: "",
+ edits: {},
});
diff --git a/src/state/store.ts b/src/state/store.ts
index 4672cfda..b0a90039 100644
--- a/src/state/store.ts
+++ b/src/state/store.ts
@@ -273,6 +273,20 @@ export const useFieldsToDisplay = () =>
export const useRecipes = () => useRecipeStore((s) => s.recipes);
export const usePackingResults = () => useRecipeStore((s) => s.packingResults);
+export const useIsLoading = () => {
+ const recipeObj = useCurrentRecipeData();
+ const selectedRecipeId = useSelectedRecipeId();
+ const inputOptions = useInputOptions();
+ return !recipeObj && !inputOptions[selectedRecipeId];
+};
+
+export const useIsModified = () => {
+ const recipeObj = useCurrentRecipeData();
+ const packingResults = useCurrentPackingResult();
+ if (!recipeObj || !packingResults) return false;
+ return !isEqual(recipeObj.edits, packingResults.edits);
+};
+
export const useCurrentRecipeObject = () => {
const recipe = useCurrentRecipeData();
return recipe
diff --git a/src/style/themeRoot.tsx b/src/style/themeRoot.tsx
index b835a577..3b3309b8 100644
--- a/src/style/themeRoot.tsx
+++ b/src/style/themeRoot.tsx
@@ -18,7 +18,9 @@ export function ThemeRoot({ children }: { children: React.ReactNode }) {
return (
- {children}
+
+ {children}
+
);
}
\ No newline at end of file
diff --git a/src/types/index.ts b/src/types/index.ts
index 64f73cc1..1d427d8f 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -46,6 +46,7 @@ export type PackingResult = {
resultUrl: string;
runTime: number;
outputDir: string;
+ edits: Record;
};
export type EditableField = {