Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenthoms committed Sep 6, 2024
1 parent 40f26eb commit c5e83ec
Show file tree
Hide file tree
Showing 17 changed files with 320 additions and 84 deletions.
20 changes: 20 additions & 0 deletions frontend/src/modules/LayerSpike/layers/Broker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { WorkbenchServices } from "@framework/WorkbenchServices";
import { WorkbenchSession } from "@framework/WorkbenchSession";

export class Broker {
private _workbenchServices: WorkbenchServices;
private _workbenchSession: WorkbenchSession;

constructor(workbenchServices: WorkbenchServices, workbenchSession: WorkbenchSession) {
this._workbenchServices = workbenchServices;
this._workbenchSession = workbenchSession;
}

getWorkbenchServices(): WorkbenchServices {
return this._workbenchServices;
}

getWorkbenchSession(): WorkbenchSession {
return this._workbenchSession;
}
}
20 changes: 3 additions & 17 deletions frontend/src/modules/LayerSpike/layers/GroupHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,8 @@ import React from "react";

import { v4 } from "uuid";

import { Item } from "./ItemBase";
import { PublishSubscribe, PublishSubscribeHandler } from "./PublishSubscribeHandler";

export interface Group extends Item {
getName(): string;
setName(name: string): void;
getGroupHandler(): GroupHandler;
}

export function instanceofGroup(item: Item): item is Group {
return (
(item as Group).getName !== undefined &&
(item as Group).setName !== undefined &&
(item as Group).getGroupHandler !== undefined
);
}
import { Item, instanceofGroup } from "./interfaces";

export enum GroupBaseTopic {
CHILDREN_CHANGED = "CHILDREN_CHANGED",
Expand Down Expand Up @@ -82,8 +68,8 @@ export class GroupHandler implements Item, PublishSubscribe<GroupBaseTopic, Grou
return child;
}

if (child instanceof GroupHandler) {
const descendant = child.findDescendantById(id);
if (instanceofGroup(child)) {
const descendant = child.getGroupHandler().findDescendantById(id);
if (descendant) {
return descendant;
}
Expand Down
3 changes: 0 additions & 3 deletions frontend/src/modules/LayerSpike/layers/ItemBase.ts

This file was deleted.

3 changes: 1 addition & 2 deletions frontend/src/modules/LayerSpike/layers/LayerBase.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { v4 } from "uuid";

import { Item } from "./ItemBase";
import { SettingsContext } from "./SettingsContext";
import { Item, SettingsContext } from "./interfaces";

export class LayerBase implements Item {
private _name: string;
Expand Down
14 changes: 14 additions & 0 deletions frontend/src/modules/LayerSpike/layers/PublishSubscribeHandler.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import React from "react";

export type TopicPayloads<TTopic extends string> = Record<TTopic, any>;

export interface PublishSubscribe<TTopic extends string, TTopicPayloads extends TopicPayloads<TTopic>> {
Expand Down Expand Up @@ -36,3 +38,15 @@ export class PublishSubscribeHandler<TTopic extends string> {
return subscriber;
}
}

export function usePublishSubscribeTopicValue<TTopic extends string, TTopicPayloads extends TopicPayloads<TTopic>>(
publishSubscribe: PublishSubscribe<TTopic, TTopicPayloads>,
topic: TTopic
): TTopicPayloads[TTopic] {
const value = React.useSyncExternalStore<TTopicPayloads[TTopic]>(
publishSubscribe.makeSubscriberFunction(topic),
publishSubscribe.makeSnapshotGetter(topic)
);

return value;
}
Empty file.
30 changes: 0 additions & 30 deletions frontend/src/modules/LayerSpike/layers/Setting.tsx

This file was deleted.

51 changes: 44 additions & 7 deletions frontend/src/modules/LayerSpike/layers/SettingsContext.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,53 @@
import { SettingBase } from "./Setting";
import { PublishSubscribe, PublishSubscribeHandler } from "./PublishSubscribeHandler";
import { Setting, SettingTopic } from "./interfaces";

export class SettingsContext {
private _settings: SettingBase<any>[] = [];
private _values: unknown[] = [];
export enum SettingsContextTopic {
AVAILABE_SETTINGS_CHANGED = "AVAILABE_SETTINGS_CHANGED",
}

export type SettingsContextTopicPayloads = {
[SettingsContextTopic.AVAILABE_SETTINGS_CHANGED]: Setting<any>[];
};

export class SettingsContextHelper implements PublishSubscribe<SettingsContextTopic, SettingsContextTopicPayloads> {
private _settings: Setting<any>[];
private _publishSubscribeHandler = new PublishSubscribeHandler<SettingsContextTopic>();
private _checkIfRefetchRequired: () => boolean;
private _fetchAvailableSettings: () => any[][];

constructor(settings: SettingBase<any>[]) {
this._settings = settings;
constructor(checkIfRefetchRequired: () => boolean, fetchAvailableSettings: () => any[][]) {
this._settings = [];
}

private maybeFetchData() {}
addSetting(setting: Setting<any>) {
this._settings.push(setting);
setting.makeSubscriberFunction(SettingTopic.VALUE_CHANGED)(() => {
this.maybeRefetchAvailableSettings();
});
}

getSettings() {
return this._settings;
}

private maybeRefetchAvailableSettings() {
if (this._checkIfRefetchRequired()) {
const newSettings = this._fetchAvailableSettings();
this._publishSubscribeHandler.notifySubscribers(SettingsContextTopic.AVAILABE_SETTINGS_CHANGED);
}
}

makeSnapshotGetter<T extends SettingsContextTopic>(topic: T): () => SettingsContextTopicPayloads[T] {
const snapshotGetter = (): any => {
if (topic === SettingsContextTopic.AVAILABE_SETTINGS_CHANGED) {
return this._settings;
}
};

return snapshotGetter;
}

makeSubscriberFunction(topic: SettingsContextTopic): (onStoreChangeCallback: () => void) => () => void {
return this._publishSubscribeHandler.makeSubscriberFunction(topic);
}
}
9 changes: 7 additions & 2 deletions frontend/src/modules/LayerSpike/layers/components/Group.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { WorkbenchSession } from "@framework/WorkbenchSession";
import { WorkbenchSettings } from "@framework/WorkbenchSettings";
import { SortableListGroup } from "@lib/components/SortableList";

import { makeComponent } from "./utils";

import { Group, GroupBaseTopic, useGroupBaseTopicValue } from "../GroupHandler";
import { GroupBaseTopic, useGroupBaseTopicValue } from "../GroupHandler";
import { Group } from "../interfaces";

export type LayerComponentProps = {
group: Group;
workbenchSettings: WorkbenchSettings;
workbenchSession: WorkbenchSession;
};

export function GroupComponent(props: LayerComponentProps): React.ReactNode {
const children = useGroupBaseTopicValue(props.group.getGroupHandler(), GroupBaseTopic.CHILDREN_CHANGED);

return (
<SortableListGroup key={props.group.getId()} id={props.group.getId()} title={props.group.getName()}>
{children.map((child) => makeComponent(child))}
{children.map((child) => makeComponent(child, props.workbenchSettings, props.workbenchSession))}
</SortableListGroup>
);
}
30 changes: 25 additions & 5 deletions frontend/src/modules/LayerSpike/layers/components/Layer.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,38 @@
import { WorkbenchSession } from "@framework/WorkbenchSession";
import { WorkbenchSettings } from "@framework/WorkbenchSettings";
import { SortableListItem } from "@lib/components/SortableList";

import { SettingComponent } from "./Setting";

import { LayerBase } from "../LayerBase";
import { Setting } from "../interfaces";

export type LayerComponentProps = {
layer: LayerBase;
onRemove: (id: string) => void;
workbenchSettings: WorkbenchSettings;
workbenchSession: WorkbenchSession;
};

export function Layer(props: LayerComponentProps): React.ReactNode {
function makeSetting(setting: Setting<any>) {
return (
<SettingComponent
key={setting.toString()}
setting={setting}
workbenchSettings={props.workbenchSettings}
workbenchSession={props.workbenchSession}
/>
);
}
return (
<SortableListItem
key={props.layer.getId()}
id={props.layer.getId()}
title={props.layer.getName()}
></SortableListItem>
<SortableListItem key={props.layer.getId()} id={props.layer.getId()} title={props.layer.getName()}>
<div className="table">
{props.layer
.getSettingsContext()
.getSettings()
.map((setting) => makeSetting(setting))}
</div>
</SortableListItem>
);
}
35 changes: 35 additions & 0 deletions frontend/src/modules/LayerSpike/layers/components/Setting.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { WorkbenchSession } from "@framework/WorkbenchSession";
import { WorkbenchSettings } from "@framework/WorkbenchSettings";

import { usePublishSubscribeTopicValue } from "../PublishSubscribeHandler";
import { Setting, SettingTopic } from "../interfaces";

export type SettingComponentProps<TValue> = {
setting: Setting<TValue>;
workbenchSettings: WorkbenchSettings;
workbenchSession: WorkbenchSession;
};

export function SettingComponent<TValue>(props: SettingComponentProps<TValue>): React.ReactNode {
const value = usePublishSubscribeTopicValue(props.setting, SettingTopic.VALUE_CHANGED);

function handleValueChanged(newValue: TValue) {
props.setting.setValue(newValue);
}

const Component = props.setting.makeComponent();
return (
<div key={props.setting.toString()} className="table-row">
<div className="table-cell align-middle p-1 text-sm">{props.setting.getLabel()}:</div>
<div className="table-cell align-middle p-1 text-sm w-full">
<Component
onValueChange={handleValueChanged}
value={value}
availableValues={props.setting.getAvailableValues()}
workbenchSettings={props.workbenchSettings}
workbenchSession={props.workbenchSession}
/>
</div>
</div>
);
}
31 changes: 26 additions & 5 deletions frontend/src/modules/LayerSpike/layers/components/utils.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,39 @@
import { WorkbenchSession } from "@framework/WorkbenchSession";
import { WorkbenchSettings } from "@framework/WorkbenchSettings";
import { SortableListItemProps } from "@lib/components/SortableList";

import { GroupComponent } from "./Group";
import { Layer } from "./Layer";

import { GroupHandler } from "../GroupHandler";
import { Item } from "../ItemBase";
import { LayerBase } from "../LayerBase";
import { Item, instanceofGroup } from "../interfaces";

export function makeComponent(item: Item): React.ReactElement<SortableListItemProps> {
export function makeComponent(
item: Item,
workbenchSettings: WorkbenchSettings,
workbenchSession: WorkbenchSession
): React.ReactElement<SortableListItemProps> {
if (item instanceof LayerBase) {
return <Layer layer={item} onRemove={() => {}} />;
return (
<Layer
key={item.getId()}
layer={item}
onRemove={() => {}}
workbenchSession={workbenchSession}
workbenchSettings={workbenchSettings}
/>
);
}
if (item instanceof GroupHandler) {
return <GroupComponent group={item} />;
if (instanceofGroup(item)) {
return (
<GroupComponent
key={item.getId()}
group={item}
workbenchSession={workbenchSession}
workbenchSettings={workbenchSettings}
/>
);
}
throw new Error("Not implemented");
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,50 @@
import React from "react";

import { EnsembleIdent } from "@framework/EnsembleIdent";
import { useEnsembleSet } from "@framework/WorkbenchSession";
import { EnsembleDropdown } from "@framework/components/EnsembleDropdown";

import { SettingBase, SettingComponentProps } from "../Setting";
import { PublishSubscribeHandler } from "../PublishSubscribeHandler";
import { Setting, SettingComponentProps, SettingTopic, SettingTopicPayloads, SettingsContext } from "../interfaces";

export class Ensemble extends SettingBase<EnsembleIdent | null> {
constructor() {
super("Ensemble", null);
export class Ensemble implements Setting<EnsembleIdent | null> {
private _value: EnsembleIdent | null = null;
private _publishSubscribeHandler = new PublishSubscribeHandler<SettingTopic>();

constructor() {}

getLabel(): string {
return "Ensemble";
}

setValue(value: EnsembleIdent | null) {
this._value = value;
this._publishSubscribeHandler.notifySubscribers(SettingTopic.VALUE_CHANGED);
}

makeComponent(): (props: SettingComponentProps<EnsembleIdent | null>) => React.ReactNode {
return function Ensemble(props: SettingComponentProps<EnsembleIdent | null>) {
return <div>{props.value ? props.value.getEnsembleName() : "No ensemble selected"}</div>;
const ensembleSet = useEnsembleSet(props.workbenchSession);

return <EnsembleDropdown ensembleSet={ensembleSet} value={props.value} onChange={props.onValueChange} />;
};
}

makeSnapshotGetter<T extends SettingTopic>(topic: T): () => SettingTopicPayloads<EnsembleIdent | null>[T] {
const snapshotGetter = (): any => {
if (topic === SettingTopic.VALUE_CHANGED) {
return this._value;
}
};

return snapshotGetter;
}

makeSubscriberFunction(topic: SettingTopic): (onStoreChangeCallback: () => void) => () => void {
return this._publishSubscribeHandler.makeSubscriberFunction(topic);
}

getAvailableValues(): (EnsembleIdent | null)[] {
return [];
}
}
Loading

0 comments on commit c5e83ec

Please sign in to comment.