Skip to content

Commit

Permalink
refactor(layerOrder): add flags to layerOrder
Browse files Browse the repository at this point in the history
Closes #1781
Closes #1722
  • Loading branch information
DamonU2 committed Feb 21, 2024
1 parent dc2a362 commit 59d6db1
Show file tree
Hide file tree
Showing 31 changed files with 714 additions and 534 deletions.
495 changes: 252 additions & 243 deletions common/config/rush/pnpm-lock.yaml

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/geoview-core/public/templates/raw-feature-info.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ <h4 id="HUC1">1. Basic Map English Geo.ca theme</h4>
'geoviewLayerType': 'esriFeature',
'listOfLayerEntryConfig': [
{
'layerId': '1'
'layerId': '1',
'initialSettings': { 'removable': false }
}
]
},
Expand Down
17 changes: 9 additions & 8 deletions packages/geoview-core/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,14 @@
"className": {
"type": "string",
"description": "A CSS class name to set to the layer element."
},
"removable": {
"type": "boolean",
"description": "Is the layer removable."
},
"hoverable": {
"type": "boolean",
"description": "Is the layer hoverable."
}
}
},
Expand Down Expand Up @@ -1888,14 +1896,7 @@
"type": "array",
"items": {
"type": "string",
"enum": [
"legend",
"layers",
"details",
"data-table",
"time-slider",
"geochart"
]
"enum": ["legend", "layers", "details", "data-table", "time-slider", "geochart"]
},
"minItems": 1,
"default": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,12 @@ export class LegendEventProcessor extends AbstractEventProcessor {
const legendLayerEntry: TypeLegendLayer = {
bounds: undefined,
layerId: layerConfig.layerId,
order:
api.maps[mapId].layer.initialLayerOrder.indexOf(entryLayerPath) !== -1 && !layerConfig.parentLayerConfig
? api.maps[mapId].layer.initialLayerOrder.indexOf(entryLayerPath)
: existingEntries.length,
// TODO: Why do we have the following line in the store? Do we have to fetch the metadata again since the GeoView layer read and keep them?
metadataAccessPath: getLocalizedValue(layerConfig.geoviewLayerConfig?.metadataAccessPath, mapId) || '',
layerPath: entryLayerPath,
layerStatus: legendResultsSetEntry.layerStatus,
layerName: getLocalizedValue(layerConfig.layerName, mapId) || layerConfig.layerId,
type: layerConfig.entryType as TypeGeoviewLayerType,
isVisible: layerConfig.initialSettings?.visible ? layerConfig.initialSettings.visible : 'yes',
canToggle: legendResultsSetEntry.data?.type !== 'esriImage',
opacity: layerConfig.initialSettings?.opacity ? layerConfig.initialSettings.opacity : 1,
items: [] as TypeLegendItem[],
Expand All @@ -180,10 +175,6 @@ export class LegendEventProcessor extends AbstractEventProcessor {
const newLegendLayer: TypeLegendLayer = {
bounds: undefined,
layerId: layerPathNodes[currentLevel],
order:
api.maps[mapId].layer.initialLayerOrder.indexOf(entryLayerPath) !== -1 && !layerConfig.parentLayerConfig
? api.maps[mapId].layer.initialLayerOrder.indexOf(entryLayerPath)
: existingEntries.length,
layerPath: entryLayerPath,
layerAttribution: api.maps[mapId].layer.geoviewLayers[layerPathNodes[0]].attributions,
// ! Why do we have metadataAccessPath here? Do we need to fetch the metadata again? The GeoView layer fetch them and store them in this.metadata.
Expand All @@ -193,7 +184,6 @@ export class LegendEventProcessor extends AbstractEventProcessor {
querySent: legendResultsSetEntry.querySent,
styleConfig: legendResultsSetEntry.data?.styleConfig,
type: legendResultsSetEntry.data?.type,
isVisible: layerConfig.initialSettings?.visible || 'yes',
canToggle: legendResultsSetEntry.data?.type !== 'esriImage',
opacity: layerConfig.initialSettings?.opacity || 1,
items: [] as TypeLegendItem[],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,24 @@ import View, { FitOptions } from 'ol/View';
import { KeyboardPan } from 'ol/interaction';

import { GeoviewStoreType } from '@/core/stores/geoview-store';
import { api, Coordinate, NORTH_POLE_POSITION, TypeBasemapOptions, TypeBasemapProps, TypeClickMarker, TypeMapFeaturesConfig } from '@/app';
import { TypeInteraction, TypeMapState, TypeValidMapProjectionCodes } from '@/geo/map/map-schema-types';
import {
api,
Coordinate,
NORTH_POLE_POSITION,
TypeBasemapOptions,
TypeBasemapProps,
TypeClickMarker,
TypeMapFeaturesConfig,
TypeOrderedLayerInfo,
} from '@/app';
import {
TypeGeoviewLayerConfig,
TypeInteraction,
TypeLayerEntryConfig,
TypeMapState,
TypeValidMapProjectionCodes,
TypeVisibilityFlags,
} from '@/geo/map/map-schema-types';
import {
mapPayload,
lngLatPayload,
Expand All @@ -21,7 +37,6 @@ import { EVENT_NAMES } from '@/api/events/event-types';
import { getGeoViewStore } from '@/core/stores/stores-managers';
import { OL_ZOOM_DURATION, OL_ZOOM_PADDING } from '@/core/utils/constant';
import { AppEventProcessor } from './app-event-processor';
import { TypeLegendLayer } from '@/core/components/layers/types';
import { logger } from '@/core/utils/logger';

import { AbstractEventProcessor } from '../abstract-event-processor';
Expand Down Expand Up @@ -189,7 +204,6 @@ export class MapEventProcessor extends AbstractEventProcessor {
unsubMapSelectedFeatures,
unsubMapZoom,
unsubMapSingleClick,
unsubLegendLayers,
];
}

Expand Down Expand Up @@ -389,6 +403,76 @@ export class MapEventProcessor extends AbstractEventProcessor {
static zoom(mapId: string, zoom: number): void {
this.getMapStateProtected(mapId).actions.setZoom(zoom, OL_ZOOM_DURATION);
}

static getMapIndexFromOrderedLayerInfo(mapId: string, layerPath: string): number {
return this.getMapStateProtected(mapId).actions.getIndexFromOrderedLayerInfo(layerPath);
}

static getMapVisibilityFromOrderedLayerInfo(mapId: string, layerPath: string): TypeVisibilityFlags {
return this.getMapStateProtected(mapId).actions.getVisibilityFromOrderedLayerInfo(layerPath);
}

static setMapHoverable(mapId: string, layerPath: string, hoverable: boolean): void {
this.getMapStateProtected(mapId).actions.setHoverable(layerPath, hoverable);
}

static setMapOrderedLayerInfo(mapId: string, orderedLayerInfo: TypeOrderedLayerInfo[]): void {
this.getMapStateProtected(mapId).actions.setOrderedLayerInfo(orderedLayerInfo);
}

static setMapQueryable(mapId: string, layerPath: string, queryable: boolean): void {
this.getMapStateProtected(mapId).actions.setQueryable(layerPath, queryable);
}

static setOrToggleMapVisibilty(mapId: string, layerPath: string, newValue?: TypeVisibilityFlags): void {
this.getMapStateProtected(mapId).actions.setOrToggleLayerVisibility(layerPath, newValue);
}

/**
* Replace a layer in the orderedLayerInfo array.
*
* @param {string} mapId The ID of the map to add the layer to.
* @param {TypeGeoviewLayerConfig} geoviewLayerConfig The config of the layer to add.
* @return {void}
*/
static replaceOrderedLayerInfo(mapId: string, geoviewLayerConfig: TypeGeoviewLayerConfig | TypeLayerEntryConfig): void {
const { orderedLayerInfo } = this.getMapStateProtected(mapId);
const layerPath = (geoviewLayerConfig as TypeGeoviewLayerConfig).geoviewLayerId
? `${(geoviewLayerConfig as TypeGeoviewLayerConfig).geoviewLayerId}/${(geoviewLayerConfig as TypeGeoviewLayerConfig).geoviewLayerId}`
: (geoviewLayerConfig as TypeLayerEntryConfig).layerPath;
const index = this.getMapIndexFromOrderedLayerInfo(mapId, layerPath);
const newOrderedLayerInfo = api.maps[mapId].layer.generateArrayOfLayerOrderInfo(geoviewLayerConfig);
orderedLayerInfo.splice(index, 1, ...newOrderedLayerInfo);
this.setMapOrderedLayerInfo(mapId, orderedLayerInfo);
}

/**
* Add a new layer to the front of the orderedLayerInfo array.
*
* @param {string} mapId The ID of the map to add the layer to.
* @param {TypeGeoviewLayerConfig} geoviewLayerConfig The config of the layer to add.
* @return {void}
*/
static addOrderedLayerInfo(mapId: string, geoviewLayerConfig: TypeGeoviewLayerConfig): void {
const { orderedLayerInfo } = this.getMapStateProtected(mapId);
const newOrderedLayerInfo = api.maps[mapId].layer.generateArrayOfLayerOrderInfo(geoviewLayerConfig);
orderedLayerInfo.unshift(...newOrderedLayerInfo);
this.setMapOrderedLayerInfo(mapId, orderedLayerInfo);
}

/**
* Remove a layer from the orderedLayerInfo array.
*
* @param {string} mapId The ID of the map to remove the layer from.
* @param {string} layerPath The path of the layer to remove.
* @return {void}
*/
static removeOrderedLayerInfo(mapId: string, layerPath: string): void {
const { orderedLayerInfo } = this.getMapStateProtected(mapId);
const newOrderedLayerInfo = orderedLayerInfo.filter((layerInfo) => !layerInfo.layerPath.startsWith(layerPath));
this.setMapOrderedLayerInfo(mapId, newOrderedLayerInfo);
}

// #endregion

// **********************************************************
Expand All @@ -412,21 +496,6 @@ export class MapEventProcessor extends AbstractEventProcessor {
api.maps[mapId].basemap.loadDefaultBasemaps(projection, language);
}

static evaluateLayerPathsFromLegendsArray(legendsArray: TypeLegendLayer[]): string[] {
const layerPathList: string[] = [];
const maxOrder = Math.max(...legendsArray.map((legendLayer) => legendLayer.order));
for (let i = 0; i <= maxOrder; i++) {
const nextLayerLegend = legendsArray.filter((layerLegend) => layerLegend.order === i)[0];
if (nextLayerLegend) {
layerPathList.push(nextLayerLegend.layerPath);
if (nextLayerLegend.children.length) {
layerPathList.push(...this.evaluateLayerPathsFromLegendsArray(nextLayerLegend.children));
}
}
}
return layerPathList;
}

static setMapKeyboardPanInteractions(mapId: string, panDelta: number): void {
const mapElement = api.maps[mapId].map;

Expand Down Expand Up @@ -556,10 +625,10 @@ export class MapEventProcessor extends AbstractEventProcessor {
* @param {string} mapId Id of map to set layer Z indices
*/
static setLayerZIndices = (mapId: string) => {
const reversedLayers = [...this.getMapStateProtected(mapId).layerOrder].reverse();
reversedLayers.forEach((layerPath, index) => {
if (api.maps[mapId].layer.registeredLayers[layerPath]?.olLayer)
api.maps[mapId].layer.registeredLayers[layerPath].olLayer?.setZIndex(index + 10);
const reversedLayers = [...this.getMapStateProtected(mapId).orderedLayerInfo].reverse();
reversedLayers.forEach((orderedLayerInfo, index) => {
if (api.maps[mapId].layer.registeredLayers[orderedLayerInfo.layerPath]?.olLayer)
api.maps[mapId].layer.registeredLayers[orderedLayerInfo.layerPath].olLayer?.setZIndex(index + 10);
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor {
// Log
logger.logTraceCoreAPIEvent('TIME SLIDER EVENT PROCESSOR - EVENT_MAP_LOADED');

const orderedLayers = store.getState().mapState.layerOrder;
const orderedLayers = store.getState().mapState.orderedLayerInfo.map((info) => info.layerPath);
const initialTimeSliderLayerPaths = TimeSliderEventProcessor.filterTimeSliderLayers(mapId, orderedLayers);
if (initialTimeSliderLayerPaths) {
initialTimeSliderLayerPaths.forEach((layerPath) => {
Expand All @@ -40,13 +40,19 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor {

// Checks for added and removed layers with time dimension
const unsubLayerOrder = store.subscribe(
(state) => state.mapState.layerOrder,
(state) => state.mapState.orderedLayerInfo,
(cur, prev) => {
// Log
logger.logTraceCoreStoreSubscription('TIME SLIDER EVENT PROCESSOR - layerOrder', cur);

const newTimeSliderLayerPaths = TimeSliderEventProcessor.filterTimeSliderLayers(mapId, cur);
const oldTimeSliderLayerPaths = TimeSliderEventProcessor.filterTimeSliderLayers(mapId, prev);
const newTimeSliderLayerPaths = TimeSliderEventProcessor.filterTimeSliderLayers(
mapId,
cur.map((info) => info.layerPath)
);
const oldTimeSliderLayerPaths = TimeSliderEventProcessor.filterTimeSliderLayers(
mapId,
prev.map((info) => info.layerPath)
);
const addedLayers = newTimeSliderLayerPaths.filter((layerPath) => !oldTimeSliderLayerPaths.includes(layerPath));
const removedLayers = oldTimeSliderLayerPaths.filter((layerPath) => !newTimeSliderLayerPaths.includes(layerPath));
if (addedLayers.length) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
useDataTableStoreRowsFiltered,
useDataTableStoreSelectedLayerPath,
useDetailsStoreLayerDataArray,
useMapVisibleLayers,
useMapOrderedLayerInfo,
} from '@/core/stores';
import { ResponsiveGrid, EnlargeButton, CloseButton, LayerList, LayerListEntry, LayerTitle, useFooterPanelHeight } from '../common';
import { logger } from '@/core/utils/logger';
Expand Down Expand Up @@ -43,7 +43,7 @@ export function Datapanel() {
const isEnlargeDataTable = useDataTableStoreIsEnlargeDataTable();
const mapFiltered = useDataTableStoreMapFilteredRecord();
const rowsFiltered = useDataTableStoreRowsFiltered();
const visibleLayers = useMapVisibleLayers();
const orderedLayerInfo = useMapOrderedLayerInfo();
const { setSelectedLayerPath, setIsEnlargeDataTable } = useDataTableStoreActions();

// Custom hook for calculating the height of footer panel
Expand All @@ -53,10 +53,17 @@ export function Datapanel() {
const mappedLayerData = useFeatureFieldInfos(layerData);

const orderedLayerData = useMemo(() => {
const visibleLayers = orderedLayerInfo
.map((layerInfo) => {
if (layerInfo.visible !== 'no') return layerInfo.layerPath;
return undefined;
})
.filter((layerPath) => layerPath !== undefined);

return visibleLayers
.map((layerPath) => mappedLayerData.filter((data) => data.layerPath === layerPath)[0])
.filter((layer) => layer !== undefined);
}, [mappedLayerData, visibleLayers]);
}, [mappedLayerData, orderedLayerInfo]);

const handleLayerChange = useCallback(
(_layer: LayerListEntry) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
CircularProgress,
} from '@/ui';
import { useUIActiveFocusItem, useUIStoreActions } from '@/core/stores/store-interface-and-intial-values/ui-state';
import { useSelectedLayerPath } from '@/core/stores/store-interface-and-intial-values/layer-state';
import { useLayerSelectedLayerPath } from '@/core/stores/store-interface-and-intial-values/layer-state';

import { FieldInfos } from './data-table';
import { getSxClasses } from './data-table-style';
Expand Down Expand Up @@ -44,7 +44,7 @@ export default function DataTableModal(): JSX.Element {
// get store function
const { closeModal } = useUIStoreActions();
const activeModalId = useUIActiveFocusItem().activeElementId;
const selectedLayer = useSelectedLayerPath();
const selectedLayer = useLayerSelectedLayerPath();

// TODO:: update when correct data is available, mean time we will be using details store data.
const layersData = useDetailsStoreLayerDataArray();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import { TypeFeatureInfoEntry, TypeLayerData, TypeGeometry, TypeArrayOfFeatureInfoEntries } from '@/api/events/payloads';
import {
useMapStoreActions,
useMapVisibleLayers,
useMapOrderedLayerInfo,
useDetailsStoreActions,
useDetailsStoreCheckedFeatures,
useDetailsStoreLayerDataArrayBatch,
Expand Down Expand Up @@ -48,7 +48,7 @@ export function DetailsPanel({ fullWidth }: DetailsPanelType): JSX.Element {
const selectedLayerPath = useDetailsStoreSelectedLayerPath();
const arrayOfLayerDataBatch = useDetailsStoreLayerDataArrayBatch();
const checkedFeatures = useDetailsStoreCheckedFeatures();
const visibleLayers = useMapVisibleLayers();
const orderedLayerInfo = useMapOrderedLayerInfo();
const { setSelectedLayerPath, removeCheckedFeature, setLayerDataArrayBatchLayerPathBypass } = useDetailsStoreActions();
const { addSelectedFeature, removeSelectedFeature } = useMapStoreActions();

Expand Down Expand Up @@ -122,7 +122,14 @@ export function DetailsPanel({ fullWidth }: DetailsPanelType): JSX.Element {
*/
const memoLayersList = useMemo(() => {
// Log
logger.logTraceUseMemo('DETAILS-PANEL - memoLayersList', visibleLayers, arrayOfLayerDataBatch);
logger.logTraceUseMemo('DETAILS-PANEL - memoLayersList', orderedLayerInfo, arrayOfLayerDataBatch);

const visibleLayers = orderedLayerInfo
.map((layerInfo) => {
if (layerInfo.visible !== 'no') return layerInfo.layerPath;
return undefined;
})
.filter((layerPath) => layerPath !== undefined);

// Set the layers list
return visibleLayers
Expand All @@ -140,7 +147,7 @@ export function DetailsPanel({ fullWidth }: DetailsPanelType): JSX.Element {
tooltip: `${layer!.layerName}, ${getNumFeaturesLabel(layer!)}`,
} as LayerListEntry)
);
}, [visibleLayers, arrayOfLayerDataBatch, getNumFeaturesLabel]);
}, [orderedLayerInfo, arrayOfLayerDataBatch, getNumFeaturesLabel]);

/**
* Memoizes the selected layer for the LayerList component.
Expand Down
Loading

0 comments on commit 59d6db1

Please sign in to comment.