From 6c58497e7ae2ec927876fde4d4a9429a6fe3b52c Mon Sep 17 00:00:00 2001 From: jorgenherje Date: Mon, 16 Oct 2023 11:55:22 +0200 Subject: [PATCH] Utilize new status writer for settings and view + bug fix - Improve usage of status writer for settings and view - Fix bug: Render `ContentError` in view withing wrapperDivRef to ensure correct sizing. --- .../SimulationTimeSeriesMatrix/settings.tsx | 26 ++++++++-- .../utils/stringUtils.ts | 12 +++++ .../SimulationTimeSeriesMatrix/view.tsx | 52 +++++++++++++------ .../SimulationTimeSeriesMatrixUtils.test.ts | 11 ++++ 4 files changed, 82 insertions(+), 19 deletions(-) create mode 100644 frontend/src/modules/SimulationTimeSeriesMatrix/utils/stringUtils.ts create mode 100644 frontend/tests/unit-tests/SimulationTimeSeriesMatrixUtils.test.ts diff --git a/frontend/src/modules/SimulationTimeSeriesMatrix/settings.tsx b/frontend/src/modules/SimulationTimeSeriesMatrix/settings.tsx index 255ffebb7..80afdf99e 100644 --- a/frontend/src/modules/SimulationTimeSeriesMatrix/settings.tsx +++ b/frontend/src/modules/SimulationTimeSeriesMatrix/settings.tsx @@ -5,6 +5,7 @@ import { EnsembleIdent } from "@framework/EnsembleIdent"; import { Parameter, ParameterIdent, ParameterType } from "@framework/EnsembleParameters"; import { EnsembleSet } from "@framework/EnsembleSet"; import { ModuleFCProps } from "@framework/Module"; +import { useSettingsStatusWriter } from "@framework/StatusWriter"; import { useEnsembleSet } from "@framework/WorkbenchSession"; import { MultiEnsembleSelect } from "@framework/components/MultiEnsembleSelect"; import { ParameterListFilter } from "@framework/components/ParameterListFilter"; @@ -39,6 +40,7 @@ import { VisualizationModeEnumToStringMapping, } from "./state"; import { EnsembleVectorListsHelper } from "./utils/ensemblesVectorListHelper"; +import { makeDisplayStringFromStringArray } from "./utils/stringUtils"; enum StatisticsType { INDIVIDUAL = "Individual", @@ -47,6 +49,7 @@ enum StatisticsType { export function settings({ moduleContext, workbenchSession }: ModuleFCProps) { const ensembleSet = useEnsembleSet(workbenchSession); + const statusWriter = useSettingsStatusWriter(moduleContext); // Store state/values const [resampleFrequency, setResamplingFrequency] = moduleContext.useStoreState("resamplingFrequency"); @@ -125,19 +128,34 @@ export function settings({ moduleContext, workbenchSession }: ModuleFCProps !ensembleVectorListsHelper.isVectorInEnsemble(ensembleIdent, vector) + ); + if (nonExistingVectors.length === 0) { + continue; + } + + const ensembleStr = ensembleSet.findEnsemble(ensembleIdent)?.getDisplayName() ?? ensembleIdent.toString(); + statusWriter.addWarning( + `Vector ${makeDisplayStringFromStringArray(nonExistingVectors)} does not exist in ensemble ${ensembleStr}` + ); + } + React.useEffect( function propagateVectorSpecsToView() { const newVectorSpecifications: VectorSpec[] = []; - for (const ensemble of selectedEnsembleIdents) { + for (const ensembleIdent of selectedEnsembleIdents) { for (const vector of selectedVectorNames) { - if (!ensembleVectorListsHelper.isVectorInEnsemble(ensemble, vector)) { + if (!ensembleVectorListsHelper.isVectorInEnsemble(ensembleIdent, vector)) { continue; } newVectorSpecifications.push({ - ensembleIdent: ensemble, + ensembleIdent: ensembleIdent, vectorName: vector, - hasHistoricalVector: ensembleVectorListsHelper.hasHistoricalVector(ensemble, vector), + hasHistoricalVector: ensembleVectorListsHelper.hasHistoricalVector(ensembleIdent, vector), }); } } diff --git a/frontend/src/modules/SimulationTimeSeriesMatrix/utils/stringUtils.ts b/frontend/src/modules/SimulationTimeSeriesMatrix/utils/stringUtils.ts new file mode 100644 index 000000000..ec686e0d2 --- /dev/null +++ b/frontend/src/modules/SimulationTimeSeriesMatrix/utils/stringUtils.ts @@ -0,0 +1,12 @@ +/** + * Utility function to make a display friendly string from an array of strings. + * + * Example: ["a", "b", "c"] -> "a, b and c" + */ +export function makeDisplayStringFromStringArray(stringArray: string[]): string { + return stringArray.length === 0 + ? "" + : stringArray.length === 1 + ? stringArray[0] + : stringArray.slice(0, -1).join(", ") + " and " + stringArray[stringArray.length - 1]; +} diff --git a/frontend/src/modules/SimulationTimeSeriesMatrix/view.tsx b/frontend/src/modules/SimulationTimeSeriesMatrix/view.tsx index 62f421ad8..0c75ab3b3 100644 --- a/frontend/src/modules/SimulationTimeSeriesMatrix/view.tsx +++ b/frontend/src/modules/SimulationTimeSeriesMatrix/view.tsx @@ -25,7 +25,6 @@ export const view = ({ moduleContext, workbenchSession, workbenchSettings }: Mod const wrapperDivSize = useElementSize(wrapperDivRef); const ensembleSet = useEnsembleSet(workbenchSession); - const statusWriter = useViewStatusWriter(moduleContext); // Store values @@ -68,6 +67,7 @@ export const view = ({ moduleContext, workbenchSession, workbenchSettings }: Mod vectorSpecificationsWithHistoricalData?.some((vec) => vec.hasHistoricalVector) ?? false ); + // Get fetching status from queries const isQueryFetching = vectorDataQueries.some((query) => query.isFetching) || vectorStatisticsQueries.some((query) => query.isFetching) || @@ -75,13 +75,18 @@ export const view = ({ moduleContext, workbenchSession, workbenchSettings }: Mod statusWriter.setLoading(isQueryFetching); - const hasQueryError = - vectorDataQueries.some((query) => query.isError) || - vectorStatisticsQueries.some((query) => query.isError) || - historicalVectorDataQueries.some((query) => query.isError); - if (hasQueryError) { - statusWriter.addError("One or more queries have an error state."); - return One or more queries have an error state.; + // Get error/warning status from queries + const hasRealizationsQueryError = vectorDataQueries.some((query) => query.isError); + const hasStatisticsQueryError = vectorStatisticsQueries.some((query) => query.isError); + const hasHistoricalVectorQueryError = historicalVectorDataQueries.some((query) => query.isError); + if (hasRealizationsQueryError) { + statusWriter.addError("One or more realization data queries have an error state."); + } + if (hasStatisticsQueryError) { + statusWriter.addError("One or more statistics data queries have an error state."); + } + if (hasHistoricalVectorQueryError) { + statusWriter.addWarning("One or more historical data queries have an error state."); } // Map vector specifications and queries with data @@ -114,12 +119,25 @@ export const view = ({ moduleContext, workbenchSession, workbenchSettings }: Mod // Create parameter color scale helper const doColorByParameter = colorRealizationsByParameter && + visualizationMode === VisualizationMode.INDIVIDUAL_REALIZATIONS && parameterIdent !== null && selectedEnsembles.some((ensemble) => ensemble.getParameters().hasParameter(parameterIdent)); const ensemblesParameterColoring = doColorByParameter ? new EnsemblesContinuousParameterColoring(selectedEnsembles, parameterIdent, parameterColorScale) : null; + // Set warning for ensembles without selected parameter when coloring is enabled + if (doColorByParameter && ensemblesParameterColoring) { + const ensemblesWithoutParameter = selectedEnsembles.filter( + (ensemble) => !ensemblesParameterColoring.hasParameterForEnsemble(ensemble.getIdent()) + ); + for (const ensemble of ensemblesWithoutParameter) { + statusWriter.addWarning( + `Ensemble ${ensemble.getDisplayName()} does not have parameter ${ensemblesParameterColoring.getParameterDisplayName()}` + ); + } + } + // Callback function for ensemble display name function makeEnsembleDisplayName(ensembleIdent: EnsembleIdent): string { const ensembleNameCount = selectedEnsembles.filter( @@ -193,16 +211,20 @@ export const view = ({ moduleContext, workbenchSession, workbenchSettings }: Mod subplotBuilder.addHistoryTraces(loadedVectorSpecificationsAndHistoricalData); } - // TODO: Keep uirevision? + const doRenderContentError = hasRealizationsQueryError || hasStatisticsQueryError; const plotData = subplotBuilder.createPlotData(); return (
- + {doRenderContentError ? ( + One or more queries have an error state. + ) : ( + + )}
); }; diff --git a/frontend/tests/unit-tests/SimulationTimeSeriesMatrixUtils.test.ts b/frontend/tests/unit-tests/SimulationTimeSeriesMatrixUtils.test.ts new file mode 100644 index 000000000..22e7190b4 --- /dev/null +++ b/frontend/tests/unit-tests/SimulationTimeSeriesMatrixUtils.test.ts @@ -0,0 +1,11 @@ +// import { scaleHexColorLightness } from "@modules/SimulationTimeSeriesMatrix/utils/colorUtils"; +import { makeDisplayStringFromStringArray } from "@modules/SimulationTimeSeriesMatrix/utils/stringUtils"; + +describe("Test of utility functions for SimulationTimeSeriesMatrix module", () => { + test("Test make display string from string array", () => { + expect(makeDisplayStringFromStringArray(["a", "b", "c"])).toBe("a, b and c"); + expect(makeDisplayStringFromStringArray(["a"])).toBe("a"); + expect(makeDisplayStringFromStringArray([])).toBe(""); + expect(makeDisplayStringFromStringArray(["a", "b"])).toBe("a and b"); + }); +});