Skip to content

Commit bedf776

Browse files
committed
Implement persistence
- Dependent on: #1110
1 parent 58c05e7 commit bedf776

File tree

9 files changed

+139
-56
lines changed

9 files changed

+139
-56
lines changed

frontend/src/modules/Intersection/loadModule.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ import { ModuleRegistry } from "@framework/ModuleRegistry";
22

33
import type { Interfaces } from "./interfaces";
44
import { settingsToViewInterfaceInitialization } from "./interfaces";
5+
import type { SerializedState } from "./persistence";
6+
import { serializeStateFunctions } from "./persistence";
57
import { MODULE_NAME } from "./registerModule";
68
import { Settings } from "./settings/settings";
79
import { View } from "./view/view";
810

9-
const module = ModuleRegistry.initModule<Interfaces>(MODULE_NAME, {
11+
const module = ModuleRegistry.initModule<Interfaces, SerializedState>(MODULE_NAME, {
1012
settingsToViewInterfaceInitialization,
13+
...serializeStateFunctions,
1114
});
1215

1316
module.viewFC = View;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type { ModuleComponentSerializationFunctions, ModuleStateSchema } from "@framework/Module";
2+
3+
import {
4+
deserializeSettings,
5+
SERIALIZED_SETTINGS_SCHEMA,
6+
serializeSettings,
7+
type SerializedSettings,
8+
} from "./settings/persistence";
9+
10+
export type SerializedState = {
11+
settings: SerializedSettings;
12+
};
13+
14+
export const SERIALIZED_STATE_SCHEMA: ModuleStateSchema<SerializedState> = {
15+
settings: SERIALIZED_SETTINGS_SCHEMA,
16+
} as const;
17+
18+
export const serializeStateFunctions: ModuleComponentSerializationFunctions<SerializedState> = {
19+
serializeStateFunctions: {
20+
settings: serializeSettings,
21+
},
22+
deserializeStateFunctions: {
23+
settings: deserializeSettings,
24+
},
25+
};

frontend/src/modules/Intersection/registerModule.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ import { ModuleRegistry } from "@framework/ModuleRegistry";
44
import { SyncSettingKey } from "@framework/SyncSettings";
55

66
import type { Interfaces } from "./interfaces";
7+
import { SERIALIZED_STATE_SCHEMA, type SerializedState } from "./persistence";
78
import { preview } from "./preview";
89

910
export const MODULE_NAME = "Intersection";
1011

11-
ModuleRegistry.registerModule<Interfaces>({
12+
ModuleRegistry.registerModule<Interfaces, SerializedState>({
1213
moduleName: MODULE_NAME,
1314
defaultTitle: "Intersection",
1415
category: ModuleCategory.MAIN,
15-
devState: ModuleDevState.DEV,
16+
devState: ModuleDevState.PROD,
1617
description: "Generic intersection viewer for co-visualization of data from various sources.",
1718
preview,
1819
dataTagIds: [
@@ -28,4 +29,5 @@ ModuleRegistry.registerModule<Interfaces>({
2829
SyncSettingKey.CAMERA_POSITION_INTERSECTION,
2930
SyncSettingKey.VERTICAL_SCALE,
3031
],
32+
serializedStateSchema: SERIALIZED_STATE_SCHEMA,
3133
});

frontend/src/modules/Intersection/settings/atoms/baseAtoms.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ import { atom } from "jotai";
33
import type { DataProviderManager } from "@modules/_shared/DataProviderFramework/framework/DataProviderManager/DataProviderManager";
44
import { PreferredViewLayout } from "@modules/Intersection/typesAndEnums";
55

6-
export const userSelectedFieldIdentifierAtom = atom<string | null>(null);
76
export const dataProviderManagerAtom = atom<DataProviderManager | null>(null);
87
export const preferredViewLayoutAtom = atom<PreferredViewLayout>(PreferredViewLayout.VERTICAL);
8+
export const dataProviderSerializedStateAtom = atom<string>("");

frontend/src/modules/Intersection/settings/atoms/derivedAtoms.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { EnsembleSetAtom } from "@framework/GlobalAtoms";
2+
import { persistableFixableAtom } from "@framework/utils/atomUtils";
3+
4+
export const selectedFieldIdentifierAtom = persistableFixableAtom<string | null>({
5+
initialValue: null,
6+
isValidFunction: ({ get, value }) => {
7+
const ensembleSet = get(EnsembleSetAtom);
8+
return (
9+
value !== null && ensembleSet.getRegularEnsembleArray().some((ens) => ens.getFieldIdentifier() === value)
10+
);
11+
},
12+
fixupFunction: ({ get }) => {
13+
const ensembleSet = get(EnsembleSetAtom);
14+
return ensembleSet.getRegularEnsembleArray().at(0)?.getFieldIdentifier() ?? null;
15+
},
16+
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import type { DeserializeStateFunction, SerializeStateFunction } from "@framework/Module";
2+
import { setIfDefined } from "@framework/utils/atomUtils";
3+
import { SchemaBuilder } from "@modules/_shared/jtd-schemas/SchemaBuilder";
4+
5+
import { PreferredViewLayout } from "../typesAndEnums";
6+
7+
import { dataProviderSerializedStateAtom, preferredViewLayoutAtom } from "./atoms/baseAtoms";
8+
import { selectedFieldIdentifierAtom } from "./atoms/persistableFixableAtoms";
9+
10+
export type SerializedSettings = {
11+
dataProviderSerializedState: string;
12+
fieldIdentifier: string | null;
13+
preferredViewLayout: PreferredViewLayout;
14+
};
15+
16+
const schemaBuilder = new SchemaBuilder<SerializedSettings>(() => ({
17+
properties: {
18+
dataProviderSerializedState: {
19+
type: "string",
20+
},
21+
fieldIdentifier: {
22+
type: "string",
23+
nullable: true,
24+
},
25+
preferredViewLayout: {
26+
enum: [PreferredViewLayout.VERTICAL, PreferredViewLayout.HORIZONTAL],
27+
},
28+
},
29+
}));
30+
31+
export const SERIALIZED_SETTINGS_SCHEMA = schemaBuilder.build();
32+
33+
export const serializeSettings: SerializeStateFunction<SerializedSettings> = (get) => {
34+
return {
35+
dataProviderSerializedState: get(dataProviderSerializedStateAtom),
36+
fieldIdentifier: get(selectedFieldIdentifierAtom).value,
37+
preferredViewLayout: get(preferredViewLayoutAtom),
38+
};
39+
};
40+
41+
export const deserializeSettings: DeserializeStateFunction<SerializedSettings> = (raw, set) => {
42+
setIfDefined(set, dataProviderSerializedStateAtom, raw.dataProviderSerializedState);
43+
setIfDefined(set, selectedFieldIdentifierAtom, raw.fieldIdentifier);
44+
setIfDefined(set, preferredViewLayoutAtom, raw.preferredViewLayout);
45+
};

frontend/src/modules/Intersection/settings/settings.tsx

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from "react";
22

33
import { useQueryClient } from "@tanstack/react-query";
4-
import { useAtom, useAtomValue, useSetAtom } from "jotai";
4+
import { useAtom } from "jotai";
55

66
import { FieldDropdown } from "@framework/components/FieldDropdown";
77
import type { ModuleSettingsProps } from "@framework/Module";
@@ -20,8 +20,8 @@ import { GroupType } from "@modules/_shared/DataProviderFramework/groups/groupTy
2020

2121
import type { Interfaces } from "../interfaces";
2222

23-
import { dataProviderManagerAtom, preferredViewLayoutAtom, userSelectedFieldIdentifierAtom } from "./atoms/baseAtoms";
24-
import { selectedFieldIdentifierAtom } from "./atoms/derivedAtoms";
23+
import { dataProviderManagerAtom, dataProviderSerializedStateAtom } from "./atoms/baseAtoms";
24+
import { selectedFieldIdentifierAtom } from "./atoms/persistableFixableAtoms";
2525
import { DataProviderManagerWrapper } from "./components/dataProviderManagerWrapper";
2626

2727
export function Settings(props: ModuleSettingsProps<Interfaces>): JSX.Element {
@@ -30,35 +30,29 @@ export function Settings(props: ModuleSettingsProps<Interfaces>): JSX.Element {
3030
const colorSet = useColorSet(props.workbenchSettings);
3131

3232
const [dataProviderManager, setDataProviderManager] = useAtom(dataProviderManagerAtom);
33+
const [selectedFieldIdentifier, setSelectedFieldIdentifier] = useAtom(selectedFieldIdentifierAtom);
3334

34-
const selectedFieldIdentifier = useAtomValue(selectedFieldIdentifierAtom);
35-
const setSelectedFieldIdentifier = useSetAtom(userSelectedFieldIdentifierAtom);
36-
const [preferredViewLayout, setPreferredViewLayout] = useAtom(preferredViewLayoutAtom);
35+
const [dataProviderSerializedState, setDataProviderSerializedState] = useAtom(dataProviderSerializedStateAtom);
36+
const dataProviderSerializedStateRef = React.useRef(dataProviderSerializedState);
3737

38-
const persistState = React.useCallback(
38+
const persistDataProviderManagerState = React.useCallback(
3939
function persistDataProviderManagerState() {
4040
if (!dataProviderManager) {
4141
return;
4242
}
4343

4444
const serializedState = {
4545
dataProviderManager: dataProviderManager.serializeState(),
46-
selectedFieldIdentifier,
47-
preferredViewLayout,
4846
};
49-
window.localStorage.setItem(
50-
`${props.settingsContext.getInstanceIdString()}-settings`,
51-
JSON.stringify(serializedState),
52-
);
47+
setDataProviderSerializedState(JSON.stringify(serializedState));
5348
},
54-
[dataProviderManager, selectedFieldIdentifier, preferredViewLayout, props.settingsContext],
49+
[dataProviderManager, setDataProviderSerializedState],
5550
);
5651

5752
const applyPersistedState = React.useCallback(
5853
function applyPersistedState(dataProviderManager: DataProviderManager) {
59-
const serializedState = window.localStorage.getItem(
60-
`${props.settingsContext.getInstanceIdString()}-settings`,
61-
);
54+
const serializedState = dataProviderSerializedStateRef.current;
55+
6256
if (!serializedState) {
6357
const groupDelegate = dataProviderManager.getGroupDelegate();
6458

@@ -80,21 +74,14 @@ export function Settings(props: ModuleSettingsProps<Interfaces>): JSX.Element {
8074
}
8175

8276
const parsedState = JSON.parse(serializedState);
83-
if (parsedState.fieldIdentifier) {
84-
setSelectedFieldIdentifier(parsedState.fieldIdentifier);
85-
}
86-
if (parsedState.preferredViewLayout) {
87-
setPreferredViewLayout(parsedState.preferredViewLayout);
88-
}
89-
9077
if (parsedState.dataProviderManager) {
9178
if (!dataProviderManager) {
9279
return;
9380
}
9481
dataProviderManager.deserializeState(parsedState.dataProviderManager);
9582
}
9683
},
97-
[setSelectedFieldIdentifier, setPreferredViewLayout, props.settingsContext, colorSet],
84+
[colorSet],
9885
);
9986

10087
React.useEffect(
@@ -121,31 +108,31 @@ export function Settings(props: ModuleSettingsProps<Interfaces>): JSX.Element {
121108
return;
122109
}
123110

124-
persistState();
111+
persistDataProviderManagerState();
125112

126113
const unsubscribeDataRev = dataProviderManager
127114
.getPublishSubscribeDelegate()
128-
.makeSubscriberFunction(DataProviderManagerTopic.DATA_REVISION)(persistState);
115+
.makeSubscriberFunction(DataProviderManagerTopic.DATA_REVISION)(persistDataProviderManagerState);
129116

130117
const unsubscribeExpands = dataProviderManager
131118
.getGroupDelegate()
132119
.getPublishSubscribeDelegate()
133-
.makeSubscriberFunction(GroupDelegateTopic.CHILDREN_EXPANSION_STATES)(persistState);
120+
.makeSubscriberFunction(GroupDelegateTopic.CHILDREN_EXPANSION_STATES)(persistDataProviderManagerState);
134121

135122
return function onUnmountEffect() {
136123
unsubscribeDataRev();
137124
unsubscribeExpands();
138125
};
139126
},
140-
[dataProviderManager, props.workbenchSession, props.workbenchSettings, persistState],
127+
[dataProviderManager, props.workbenchSession, props.workbenchSettings, persistDataProviderManagerState],
141128
);
142129

143130
React.useEffect(
144131
function onFieldIdentifierChangedEffect() {
145132
if (!dataProviderManager) {
146133
return;
147134
}
148-
dataProviderManager.updateGlobalSetting("fieldId", selectedFieldIdentifier);
135+
dataProviderManager.updateGlobalSetting("fieldId", selectedFieldIdentifier.value);
149136
},
150137
[selectedFieldIdentifier, dataProviderManager],
151138
);
@@ -159,7 +146,7 @@ export function Settings(props: ModuleSettingsProps<Interfaces>): JSX.Element {
159146
<CollapsibleGroup title="Field" expanded>
160147
<FieldDropdown
161148
ensembleSet={ensembleSet}
162-
value={selectedFieldIdentifier}
149+
value={selectedFieldIdentifier.value}
163150
onChange={handleFieldIdentifierChange}
164151
/>
165152
</CollapsibleGroup>

frontend/src/modules/ModuleSerializedStateMap.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Generated by generateModuleSerializedStateMap CLI
33

44
import type { SerializedSettings as M_2DViewerSettings } from "@modules/2DViewer/settings/persistence";
5+
import type { SerializedSettings as IntersectionSettings } from "@modules/Intersection/settings/persistence";
56
import type { SerializedSettings as MyModuleSettings } from "@modules/MyModule/settings/persistence";
67
import type { SerializedView as M_2DViewerView } from "@modules/2DViewer/view/persistence";
78

@@ -30,6 +31,10 @@ export type ModuleSerializedStateMap = {
3031
settings?: never,
3132
view?: never,
3233
},
34+
"Grid3DIntersection": {
35+
settings?: never,
36+
view?: never,
37+
},
3338
"InplaceVolumesPlot": {
3439
settings?: never,
3540
view?: never,
@@ -39,7 +44,7 @@ export type ModuleSerializedStateMap = {
3944
view?: never,
4045
},
4146
"Intersection": {
42-
settings?: never,
47+
settings?: Partial<IntersectionSettings>,
4348
view?: never,
4449
},
4550
"Map": {
@@ -82,6 +87,18 @@ export type ModuleSerializedStateMap = {
8287
settings?: never,
8388
view?: never,
8489
},
90+
"SeismicIntersection": {
91+
settings?: never,
92+
view?: never,
93+
},
94+
"SeismicMap": {
95+
settings?: never,
96+
view?: never,
97+
},
98+
"Sensitivity": {
99+
settings?: never,
100+
view?: never,
101+
},
85102
"SimulationTimeSeries": {
86103
settings?: never,
87104
view?: never,
@@ -90,6 +107,10 @@ export type ModuleSerializedStateMap = {
90107
settings?: never,
91108
view?: never,
92109
},
110+
"StructuralUncertaintyIntersection": {
111+
settings?: never,
112+
view?: never,
113+
},
93114
"SubsurfaceMap": {
94115
settings?: never,
95116
view?: never,
@@ -98,6 +119,10 @@ export type ModuleSerializedStateMap = {
98119
settings?: never,
99120
view?: never,
100121
},
122+
"TopographicMap": {
123+
settings?: never,
124+
view?: never,
125+
},
101126
"TornadoChart": {
102127
settings?: never,
103128
view?: never,

0 commit comments

Comments
 (0)