diff --git a/frontend/src/modules/Intersection/settings/atoms/derivedAtoms.ts b/frontend/src/modules/Intersection/settings/atoms/derivedAtoms.ts index 9652f8922..d2dcf62c4 100644 --- a/frontend/src/modules/Intersection/settings/atoms/derivedAtoms.ts +++ b/frontend/src/modules/Intersection/settings/atoms/derivedAtoms.ts @@ -1,4 +1,5 @@ import { EnsembleIdent } from "@framework/EnsembleIdent"; +import { EnsembleSet } from "@framework/EnsembleSet"; import { EnsembleRealizationFilterFunctionAtom, EnsembleSetAtom } from "@framework/GlobalAtoms"; import { IntersectionPolylinesAtom } from "@framework/userCreatedItems/IntersectionPolylines"; @@ -12,6 +13,17 @@ import { } from "./baseAtoms"; import { drilledWellboreHeadersQueryAtom } from "./queryAtoms"; +export const filteredEnsembleSetAtom = atom((get) => { + const ensembleSet = get(EnsembleSetAtom); + const fieldIdentifier = get(userSelectedFieldIdentifierAtom); + + if (fieldIdentifier === null) { + return ensembleSet; + } + + return new EnsembleSet(ensembleSet.getEnsembleArr().filter((el) => el.getFieldIdentifier() === fieldIdentifier)); +}); + export const selectedFieldIdentifierAtom = atom((get) => { const ensembleSet = get(EnsembleSetAtom); const selectedFieldIdentifier = get(userSelectedFieldIdentifierAtom); diff --git a/frontend/src/modules/Intersection/settings/settings.tsx b/frontend/src/modules/Intersection/settings/settings.tsx index 91723b5cd..325b48d67 100644 --- a/frontend/src/modules/Intersection/settings/settings.tsx +++ b/frontend/src/modules/Intersection/settings/settings.tsx @@ -26,6 +26,7 @@ import { } from "./atoms/baseAtoms"; import { availableUserCreatedIntersectionPolylinesAtom, + filteredEnsembleSetAtom, selectedCustomIntersectionPolylineIdAtom, selectedFieldIdentifierAtom, selectedWellboreAtom, @@ -41,6 +42,7 @@ export function Settings( props: ModuleSettingsProps, ViewAtoms> ): JSX.Element { const ensembleSet = useEnsembleSet(props.workbenchSession); + const filteredEnsembleSet = useAtomValue(filteredEnsembleSetAtom); const statusWriter = useSettingsStatusWriter(props.settingsContext); const selectedField = useAtomValue(selectedFieldIdentifierAtom); @@ -192,7 +194,7 @@ export function Settings(
diff --git a/frontend/src/modules/Intersection/utils/layers/BaseLayer.ts b/frontend/src/modules/Intersection/utils/layers/BaseLayer.ts index de76fc0e1..070548e48 100644 --- a/frontend/src/modules/Intersection/utils/layers/BaseLayer.ts +++ b/frontend/src/modules/Intersection/utils/layers/BaseLayer.ts @@ -34,7 +34,7 @@ export type LayerSettings = { export class BaseLayer { private _subscribers: Map void>> = new Map(); - protected _queryClient: QueryClient; + protected _queryClient: QueryClient | null = null; protected _status: LayerStatus = LayerStatus.IDLE; private _id: string; private _name: string; @@ -46,12 +46,11 @@ export class BaseLayer { private _lastDataFetchSettings: TSettings; private _queryKeys: unknown[][] = []; - constructor(name: string, settings: TSettings, queryClient: QueryClient) { + constructor(name: string, settings: TSettings) { this._id = v4(); this._name = name; this._settings = settings; this._lastDataFetchSettings = cloneDeep(settings); - this._queryClient = queryClient; } getId(): string { @@ -78,6 +77,10 @@ export class BaseLayer { this.notifySubscribers(LayerTopic.NAME); } + setQueryClient(queryClient: QueryClient): void { + this._queryClient = queryClient; + } + getBoundingBox(): BoundingBox | null { return this._boundingBox; } @@ -132,6 +135,10 @@ export class BaseLayer { } private maybeCancelQuery(): void { + if (!this._queryClient) { + return; + } + if (this._queryKeys) { for (const queryKey of this._queryKeys) { this._queryClient.cancelQueries({ queryKey }); @@ -169,6 +176,9 @@ export class BaseLayer { } async maybeRefetchData(): Promise { + if (!this._queryClient) { + return; + } if (this._isSuspended) { return; } @@ -187,7 +197,7 @@ export class BaseLayer { this._status = LayerStatus.LOADING; this.notifySubscribers(LayerTopic.STATUS); try { - this._data = await this.fetchData(); + this._data = await this.fetchData(this._queryClient); if (this._queryKeys.length === null && isDevMode()) { console.warn( "Did you forget to use 'setQueryKeys' in your layer implementation of 'fetchData'? This will cause the queries to not be cancelled when settings change and might lead to undesired behaviour." @@ -203,7 +213,7 @@ export class BaseLayer { this.notifySubscribers(LayerTopic.STATUS); } - protected async fetchData(): Promise { + protected async fetchData(queryClient: QueryClient): Promise { throw new Error("Not implemented"); } } diff --git a/frontend/src/modules/Intersection/utils/layers/GridLayer.ts b/frontend/src/modules/Intersection/utils/layers/GridLayer.ts index 757959255..ec65f0b58 100644 --- a/frontend/src/modules/Intersection/utils/layers/GridLayer.ts +++ b/frontend/src/modules/Intersection/utils/layers/GridLayer.ts @@ -36,7 +36,7 @@ export class GridLayer extends BaseLayer(); private _defaultColorScale: ColorScale; - constructor(name: string, queryClient: QueryClient) { + constructor(name: string) { const defaultSettings = { ensembleIdent: null, gridModelName: null, @@ -50,7 +50,7 @@ export class GridLayer extends BaseLayer { + protected async fetchData(queryClient: QueryClient): Promise { super.setBoundingBox(null); const queryKey = ["getGridPolylineIntersection", ...Object.entries(this._settings)]; this.registerQueryKey(queryKey); - return this._queryClient + return queryClient .fetchQuery({ queryKey, queryFn: () => diff --git a/frontend/src/modules/Intersection/utils/layers/LayerManager.ts b/frontend/src/modules/Intersection/utils/layers/LayerManager.ts new file mode 100644 index 000000000..95eebb677 --- /dev/null +++ b/frontend/src/modules/Intersection/utils/layers/LayerManager.ts @@ -0,0 +1,56 @@ +import { QueryClient } from "@tanstack/query-core"; + +import { BaseLayer } from "./BaseLayer"; + +export enum LayerManagerTopics { + LAYERS_CHANGED = "layers-changed", +} + +export class LayerManager { + private _queryClient: QueryClient; + private _layers: BaseLayer[] = []; + private _subscribers: Map void>> = new Map(); + + constructor(queryClient: QueryClient) { + this._queryClient = queryClient; + } + + addLayer(layer: BaseLayer): void { + layer.setName(this.makeUniqueLayerName(layer.getName())); + layer.setQueryClient(this._queryClient); + this._layers.push(layer); + this.notifySubscribers(LayerManagerTopics.LAYERS_CHANGED); + } + + removeLayer(id: string): void { + this._layers = this._layers.filter((layer) => layer.getId() !== id); + } + + getLayer(id: string): BaseLayer | undefined { + return this._layers.find((layer) => layer.getId() === id); + } + + changeOrder(order: string[]): void { + this._layers = order + .map((id) => this._layers.find((layer) => layer.getId() === id)) + .filter(Boolean) as BaseLayer[]; + this.notifySubscribers(LayerManagerTopics.LAYERS_CHANGED); + } + + private notifySubscribers(topic: LayerManagerTopics): void { + const subscribers = this._subscribers.get(topic); + if (subscribers) { + subscribers.forEach((subscriber) => subscriber()); + } + } + + private makeUniqueLayerName(name: string): string { + let potentialName = name; + let i = 1; + while (this._layers.some((layer) => layer.getName() === potentialName)) { + potentialName = `${name} (${i})`; + i++; + } + return potentialName; + } +} diff --git a/frontend/src/modules/Intersection/utils/layers/SeismicLayer.ts b/frontend/src/modules/Intersection/utils/layers/SeismicLayer.ts index 618f1130b..ff965994e 100644 --- a/frontend/src/modules/Intersection/utils/layers/SeismicLayer.ts +++ b/frontend/src/modules/Intersection/utils/layers/SeismicLayer.ts @@ -74,7 +74,7 @@ export class SeismicLayer extends BaseLayer = new Map(); private _useCustomColorScaleBoundariesParameterMap = new Map(); - constructor(name: string, queryClient: QueryClient) { + constructor(name: string) { const defaultSettings = { ensembleIdent: null, realizationNum: null, @@ -86,7 +86,7 @@ export class SeismicLayer extends BaseLayer { + protected async fetchData(queryClient: QueryClient): Promise { super.setBoundingBox(null); const sampledPolyline = this.samplePolyline(); @@ -340,7 +340,7 @@ export class SeismicLayer extends BaseLayer diff --git a/frontend/src/modules/Intersection/utils/layers/SurfaceLayer.ts b/frontend/src/modules/Intersection/utils/layers/SurfaceLayer.ts index 562970e17..6387e1194 100644 --- a/frontend/src/modules/Intersection/utils/layers/SurfaceLayer.ts +++ b/frontend/src/modules/Intersection/utils/layers/SurfaceLayer.ts @@ -26,7 +26,7 @@ export type SurfaceLayerSettings = { export class SurfaceLayer extends BaseLayer { private _colorSet: ColorSet; - constructor(name: string, queryClient: QueryClient) { + constructor(name: string) { const defaultSettings = { ensembleIdent: null, realizationNum: null, @@ -36,7 +36,7 @@ export class SurfaceLayer extends BaseLayer { + protected async fetchData(queryClient: QueryClient): Promise { const promises: Promise[] = []; super.setBoundingBox(null); @@ -181,7 +181,7 @@ export class SurfaceLayer extends BaseLayer apiService.surface.postGetSurfaceIntersection( diff --git a/frontend/src/modules/Intersection/utils/layers/SurfacesUncertaintyLayer.ts b/frontend/src/modules/Intersection/utils/layers/SurfacesUncertaintyLayer.ts index b6d7a2e5e..c235ae0cf 100644 --- a/frontend/src/modules/Intersection/utils/layers/SurfacesUncertaintyLayer.ts +++ b/frontend/src/modules/Intersection/utils/layers/SurfacesUncertaintyLayer.ts @@ -45,7 +45,7 @@ function transformData( export class SurfacesUncertaintyLayer extends BaseLayer { private _colorSet: ColorSet; - constructor(name: string, queryClient: QueryClient) { + constructor(name: string) { const defaultSettings = { ensembleIdent: null, realizationNums: [], @@ -55,7 +55,7 @@ export class SurfacesUncertaintyLayer extends BaseLayer { + protected async fetchData(queryClient: QueryClient): Promise { const promises: Promise[] = []; super.setBoundingBox(null); @@ -214,7 +214,7 @@ export class SurfacesUncertaintyLayer extends BaseLayer diff --git a/frontend/src/modules/Intersection/utils/layers/WellpicksLayer.ts b/frontend/src/modules/Intersection/utils/layers/WellpicksLayer.ts index c98239aa4..3da88f844 100644 --- a/frontend/src/modules/Intersection/utils/layers/WellpicksLayer.ts +++ b/frontend/src/modules/Intersection/utils/layers/WellpicksLayer.ts @@ -21,7 +21,7 @@ export type WellpicksLayerSettings = { export type WellPicksLayerData = ReturnType; export class WellpicksLayer extends BaseLayer { - constructor(name: string, queryClient: QueryClient) { + constructor(name: string) { const defaultSettings = { ensembleIdent: null, wellboreUuid: null, @@ -29,7 +29,7 @@ export class WellpicksLayer extends BaseLayer { + protected async fetchData(queryClient: QueryClient): Promise { const queryKey = [ "getWellborePicksAndStratigraphicUnits", this._settings.ensembleIdent?.getCaseUuid(), @@ -72,7 +72,7 @@ export class WellpicksLayer extends BaseLayer