Skip to content

Commit

Permalink
Adjusted according to review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenthoms committed Dec 12, 2024
1 parent a71c1ab commit 37e145c
Show file tree
Hide file tree
Showing 58 changed files with 316 additions and 356 deletions.
4 changes: 2 additions & 2 deletions frontend/src/modules/2DViewer/layers/ColorScale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ColorScale as ColorScaleImpl } from "@lib/utils/ColorScale";

import { LayerManager, LayerManagerTopic } from "./LayerManager";
import { ItemDelegate } from "./delegates/ItemDelegate";
import { Item, SerializedColorScale } from "./interfaces";
import { Item, SerializedColorScale, SerializedType } from "./interfaces";

export class ColorScale implements Item {
private _itemDelegate: ItemDelegate;
Expand Down Expand Up @@ -45,7 +45,7 @@ export class ColorScale implements Item {
serializeState(): SerializedColorScale {
return {
...this._itemDelegate.serializeState(),
type: "color-scale",
type: SerializedType.COLOR_SCALE,
colorScale: this._colorScale.serialize(),
userDefinedBoundaries: this._areBoundariesUserDefined,
};
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/modules/2DViewer/layers/DeltaSurface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ItemDelegate } from "./delegates/ItemDelegate";
import { LayerDelegate } from "./delegates/LayerDelegate";
import { SettingsContextDelegateTopic } from "./delegates/SettingsContextDelegate";
import { UnsubscribeHandlerDelegate } from "./delegates/UnsubscribeHandlerDelegate";
import { Group, SerializedDeltaSurface, instanceofLayer } from "./interfaces";
import { Group, SerializedDeltaSurface, SerializedType, instanceofLayer } from "./interfaces";

export class DeltaSurface implements Group {
private _itemDelegate: ItemDelegate;
Expand Down Expand Up @@ -59,7 +59,6 @@ export class DeltaSurface implements Group {

private handleSettingsChange(): void {
console.debug("Settings changed - would refetch data");
// Fetch data
}

getItemDelegate(): ItemDelegate {
Expand All @@ -78,7 +77,7 @@ export class DeltaSurface implements Group {
serializeState(): SerializedDeltaSurface {
return {
...this._itemDelegate.serializeState(),
type: "delta-surface",
type: SerializedType.DELTA_SURFACE,
children: this.getGroupDelegate().serializeChildren(),
};
}
Expand Down
15 changes: 13 additions & 2 deletions frontend/src/modules/2DViewer/layers/Dependency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ import { GlobalSettings } from "./LayerManager";
import { SettingsContextDelegate } from "./delegates/SettingsContextDelegate";
import { Settings, UpdateFunc } from "./interfaces";

/*
* Dependency class is used to represent a node in the dependency graph of a layer settings context.
* It can be compared to an atom in Jotai.
*
* It can subscribe to both changes in settings (local and global) and other dependencies.
* Its value is calculated by an update function that is provided during initialization.
* The update function is called whenever any of the dependencies change.
* All entities that this dependency depends on are cached such that they are only updated when they change,
* not when they are accessed.
* The dependency can be subscribed to, and will notify its subscribers whenever its value changes.
*/
export class Dependency<TReturnValue, TSettings extends Settings, TKey extends keyof TSettings> {
private _updateFunc: UpdateFunc<TReturnValue, TSettings, TKey>;
private _dependencies: Set<(value: Awaited<TReturnValue> | null) => void> = new Set();
Expand Down Expand Up @@ -169,7 +180,7 @@ export class Dependency<TReturnValue, TSettings extends Settings, TKey extends k
this._isInitialized = true;
}

async callUpdateFunc() {
private async callUpdateFunc() {
if (this._abortController) {
this._abortController.abort();
this._abortController = null;
Expand Down Expand Up @@ -198,7 +209,7 @@ export class Dependency<TReturnValue, TSettings extends Settings, TKey extends k
this.applyNewValue(newValue);
}

applyNewValue(newValue: Awaited<TReturnValue> | null) {
private applyNewValue(newValue: Awaited<TReturnValue> | null) {
this.setLoadingState(false);
if (!isEqual(newValue, this._cachedValue) || newValue === null) {
this._cachedValue = newValue;
Expand Down
23 changes: 13 additions & 10 deletions frontend/src/modules/2DViewer/layers/DeserializationFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
SerializedLayer,
SerializedSettingsGroup,
SerializedSharedSetting,
SerializedType,
SerializedView,
} from "./interfaces";

Expand All @@ -23,7 +24,13 @@ export class DeserializationFactory {
}

makeItem(serialized: SerializedItem): Item {
if (serialized.type === "layer") {
if (serialized.type === SerializedType.LAYER_MANAGER) {
throw new Error(
"Cannot deserialize a LayerManager in DeserializationFactory. A LayerManager can never be a descendant of a LayerManager."
);
}

if (serialized.type === SerializedType.LAYER) {
const serializedLayer = serialized as SerializedLayer<any>;
const layer = LayerRegistry.makeLayer(serializedLayer.layerClass, this._layerManager);
layer.getLayerDelegate().deserializeState(serializedLayer);
Expand All @@ -32,39 +39,35 @@ export class DeserializationFactory {
return layer;
}

if (serialized.type === "view") {
if (serialized.type === SerializedType.VIEW) {
const serializedView = serialized as SerializedView;
const view = new View(serializedView.name, this._layerManager, serializedView.color);
view.deserializeState(serializedView);
return view;
}

if (serialized.type === "settings-group") {
if (serialized.type === SerializedType.SETTINGS_GROUP) {
const serializedSettingsGroup = serialized as SerializedSettingsGroup;
const settingsGroup = new SettingsGroup(serializedSettingsGroup.name, this._layerManager);
settingsGroup.deserializeState(serializedSettingsGroup);
return settingsGroup;
}

if (serialized.type === "color-scale") {
if (serialized.type === SerializedType.COLOR_SCALE) {
const serializedColorScale = serialized as SerializedColorScale;
const colorScale = new ColorScale(serializedColorScale.name, this._layerManager);
colorScale.deserializeState(serializedColorScale);
return colorScale;
}

if (serialized.type === "delta-surface") {
throw new Error("DeltaSurface deserialization not implemented");
}

if (serialized.type === "shared-setting") {
if (serialized.type === SerializedType.SHARED_SETTING) {
const serializedSharedSetting = serialized as SerializedSharedSetting;
const wrappedSetting = SettingRegistry.makeSetting(serializedSharedSetting.wrappedSettingClass);
const setting = new SharedSetting(wrappedSetting, this._layerManager);
setting.deserializeState(serializedSharedSetting);
return setting;
}

throw new Error(`Unknown serialized item type: ${serialized.type}`);
throw new Error(`Unhandled serialized item type: ${serialized.type}`);
}
}
14 changes: 12 additions & 2 deletions frontend/src/modules/2DViewer/layers/LayerManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { GroupDelegate, GroupDelegateTopic } from "./delegates/GroupDelegate";
import { ItemDelegate } from "./delegates/ItemDelegate";
import { PublishSubscribe, PublishSubscribeDelegate } from "./delegates/PublishSubscribeDelegate";
import { UnsubscribeHandlerDelegate } from "./delegates/UnsubscribeHandlerDelegate";
import { Group, Item, SerializedLayerManager } from "./interfaces";
import { Group, Item, SerializedLayerManager, SerializedType } from "./interfaces";

export enum LayerManagerTopic {
ITEMS_CHANGED = "ITEMS_CHANGED",
Expand All @@ -40,6 +40,16 @@ export type GlobalSettings = {
realizationFilterFunction: EnsembleRealizationFilterFunction;
};

/*
* The LayerManager class is responsible for managing all items (layers, views, settings, etc.).
* It is the main ancestor of all items and provides a way to subscribe/publish messages to all descendants.
* Moreover, it is responsible for managing the global settings coming from the framework (e.g. ensembles, fieldId).
* It also holds the revision number of the layer data, which is used to notify subscribers when any layer data changes.
* This makes it possible to update the GUI accordingly.
* The LayerManager class is also responsible for serializing/deserializing the state of itself and all its descendants.
* It does also serve as a provider of the QueryClient and WorkbenchSession.
*/

export class LayerManager implements Group, PublishSubscribe<LayerManagerTopic, LayerManagerTopicPayload> {
private _workbenchSession: WorkbenchSession;
private _workbenchSettings: WorkbenchSettings;
Expand Down Expand Up @@ -168,7 +178,7 @@ export class LayerManager implements Group, PublishSubscribe<LayerManagerTopic,
const itemState = this._itemDelegate.serializeState();
return {
...itemState,
type: "layer-manager",
type: SerializedType.LAYER_MANAGER,
children: this._groupDelegate.serializeChildren(),
};
}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/modules/2DViewer/layers/SettingsGroup.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { LayerManager } from "./LayerManager";
import { GroupDelegate } from "./delegates/GroupDelegate";
import { ItemDelegate } from "./delegates/ItemDelegate";
import { Group, SerializedSettingsGroup } from "./interfaces";
import { Group, SerializedSettingsGroup, SerializedType } from "./interfaces";

export class SettingsGroup implements Group {
private _itemDelegate: ItemDelegate;
Expand All @@ -24,7 +24,7 @@ export class SettingsGroup implements Group {
serializeState(): SerializedSettingsGroup {
return {
...this._itemDelegate.serializeState(),
type: "settings-group",
type: SerializedType.SETTINGS_GROUP,
children: this._groupDelegate.serializeChildren(),
};
}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/modules/2DViewer/layers/SharedSetting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { LayerManager, LayerManagerTopic } from "./LayerManager";
import { ItemDelegate } from "./delegates/ItemDelegate";
import { SettingTopic } from "./delegates/SettingDelegate";
import { UnsubscribeHandlerDelegate } from "./delegates/UnsubscribeHandlerDelegate";
import { Item, Layer, SerializedSharedSetting, Setting, instanceofLayer } from "./interfaces";
import { Item, Layer, SerializedSharedSetting, SerializedType, Setting, instanceofLayer } from "./interfaces";

export class SharedSetting implements Item {
private _wrappedSetting: Setting<any>;
Expand Down Expand Up @@ -100,7 +100,7 @@ export class SharedSetting implements Item {
serializeState(): SerializedSharedSetting {
return {
...this._itemDelegate.serializeState(),
type: "shared-setting",
type: SerializedType.SHARED_SETTING,
wrappedSettingClass: this._wrappedSetting.constructor.name,
settingType: this._wrappedSetting.getType(),
value: this._wrappedSetting.getDelegate().serializeValue(),
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/modules/2DViewer/layers/View.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { LayerManager } from "./LayerManager";
import { GroupDelegate } from "./delegates/GroupDelegate";
import { ItemDelegate } from "./delegates/ItemDelegate";
import { Group, SerializedView } from "./interfaces";
import { Group, SerializedType, SerializedView } from "./interfaces";

export class View implements Group {
private _itemDelegate: ItemDelegate;
Expand All @@ -24,7 +24,7 @@ export class View implements Group {
serializeState(): SerializedView {
return {
...this._itemDelegate.serializeState(),
type: "view",
type: SerializedType.VIEW,
color: this._groupDelegate.getColor() ?? "",
children: this._groupDelegate.serializeChildren(),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { resolveClassNames } from "@lib/utils/resolveClassNames";
import { ColorScaleSelector } from "@modules/_shared/components/ColorScaleSelector/colorScaleSelector";
import { ExpandLess, ExpandMore } from "@mui/icons-material";

import { RemoveButton } from "./RemoveButton";
import { RemoveItemButton } from "./RemoveItemButton";

import { ColorScale } from "../ColorScale";
import { ItemDelegateTopic } from "../delegates/ItemDelegate";
Expand Down Expand Up @@ -63,7 +63,7 @@ export function ColorScaleComponent(props: ColorScaleComponentProps): React.Reac
<Icon data={color_palette} size={16} />
</div>
}
endAdornment={<RemoveButton item={props.colorScale} />}
endAdornment={<RemoveItemButton item={props.colorScale} />}
>
<div className={resolveClassNames("p-2 text-sm border", { hidden: !isExpanded })}>
{makeColorScaleSelector()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { EditName } from "./EditName";
import { EmptyContent } from "./EmptyContent";
import { ExpandCollapseAllButton } from "./ExpandCollapseAllButton";
import { LayersActionGroup, LayersActions } from "./LayersActions";
import { RemoveButton } from "./RemoveButton";
import { RemoveItemButton } from "./RemoveItemButton";
import { VisibilityToggle } from "./VisibilityToggle";
import { makeComponent } from "./utils";
import { makeSortableListItemComponent } from "./utils";

import { DeltaSurface } from "../DeltaSurface";
import { GroupDelegateTopic } from "../delegates/GroupDelegate";
Expand Down Expand Up @@ -46,7 +46,7 @@ export function DeltaSurfaceComponent(props: DeltaSurfaceComponentProps): React.
);
}
adornment.push(<ExpandCollapseAllButton key="expand-collapse" group={props.deltaSurface} />);
adornment.push(<RemoveButton key="remove" item={props.deltaSurface} />);
adornment.push(<RemoveItemButton key="remove" item={props.deltaSurface} />);
return adornment;
}

Expand All @@ -72,7 +72,7 @@ export function DeltaSurfaceComponent(props: DeltaSurfaceComponentProps): React.
}
expanded={isExpanded}
>
{children.map((child: Item) => makeComponent(child, props.actions, props.onActionClick))}
{children.map((child: Item) => makeSortableListItemComponent(child, props.actions, props.onActionClick))}
</SortableListGroup>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { resolveClassNames } from "@lib/utils/resolveClassNames";
import { Block, CheckCircle, Difference, Error, ExpandLess, ExpandMore } from "@mui/icons-material";

import { EditName } from "./EditName";
import { RemoveButton } from "./RemoveButton";
import { RemoveItemButton } from "./RemoveItemButton";
import { SettingComponent } from "./SettingComponent";
import { VisibilityToggle } from "./VisibilityToggle";

Expand Down Expand Up @@ -161,7 +161,7 @@ function EndActions(props: EndActionProps): React.ReactNode {
return (
<>
{makeStatus()}
<RemoveButton item={props.layer} />
<RemoveItemButton item={props.layer} />
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { Delete } from "@mui/icons-material";

import { Item, instanceofLayer } from "../interfaces";

export type RemoveButtonProps = {
export type RemoveItemButtonProps = {
item: Item;
};

export function RemoveButton(props: RemoveButtonProps): React.ReactNode {
export function RemoveItemButton(props: RemoveItemButtonProps): React.ReactNode {
function handleRemove() {
const parentGroup = props.item.getItemDelegate().getParentGroup();
if (parentGroup) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { SettingsApplications } from "@mui/icons-material";
import { EmptyContent } from "./EmptyContent";
import { ExpandCollapseAllButton } from "./ExpandCollapseAllButton";
import { LayersActionGroup, LayersActions } from "./LayersActions";
import { RemoveButton } from "./RemoveButton";
import { makeComponent } from "./utils";
import { RemoveItemButton } from "./RemoveItemButton";
import { makeSortableListItemComponent } from "./utils";

import { GroupDelegateTopic } from "../delegates/GroupDelegate";
import { ItemDelegateTopic } from "../delegates/ItemDelegate";
Expand Down Expand Up @@ -41,7 +41,7 @@ export function SettingsGroupComponent(props: SettingsGroupComponentProps): Reac
);
}
adornment.push(<ExpandCollapseAllButton key="expand-collapse" group={props.group} />);
adornment.push(<RemoveButton key="remove" item={props.group} />);
adornment.push(<RemoveItemButton key="remove" item={props.group} />);
return adornment;
}

Expand All @@ -67,7 +67,7 @@ export function SettingsGroupComponent(props: SettingsGroupComponentProps): Reac
}
expanded={isExpanded}
>
{children.map((child: Item) => makeComponent(child, props.actions, props.onActionClick))}
{children.map((child: Item) => makeSortableListItemComponent(child, props.actions, props.onActionClick))}
</SortableListGroup>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { EditName } from "./EditName";
import { EmptyContent } from "./EmptyContent";
import { ExpandCollapseAllButton } from "./ExpandCollapseAllButton";
import { LayersActionGroup, LayersActions } from "./LayersActions";
import { RemoveButton } from "./RemoveButton";
import { RemoveItemButton } from "./RemoveItemButton";
import { VisibilityToggle } from "./VisibilityToggle";
import { makeComponent } from "./utils";
import { makeSortableListItemComponent } from "./utils";

import { GroupDelegateTopic } from "../delegates/GroupDelegate";
import { ItemDelegateTopic } from "../delegates/ItemDelegate";
Expand Down Expand Up @@ -42,7 +42,7 @@ export function ViewComponent(props: ViewComponentProps): React.ReactNode {
);
}
adornments.push(<ExpandCollapseAllButton key="expand-collapse" group={props.group} />);
adornments.push(<RemoveButton key="remove" item={props.group} />);
adornments.push(<RemoveItemButton key="remove" item={props.group} />);
return adornments;
}

Expand Down Expand Up @@ -71,7 +71,7 @@ export function ViewComponent(props: ViewComponentProps): React.ReactNode {
endAdornment={<>{makeEndAdornment()}</>}
contentWhenEmpty={<EmptyContent>Drag a layer inside to add it to this view.</EmptyContent>}
>
{children.map((child: Item) => makeComponent(child, props.actions, props.onActionClick))}
{children.map((child: Item) => makeSortableListItemComponent(child, props.actions, props.onActionClick))}
</SortableListGroup>
);
}
Loading

0 comments on commit 37e145c

Please sign in to comment.