Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugins): Hides plugin tabs if no layers support them #2384

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/type-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ jobs:
rm -r common
rm -r packages

git config --global user.name $USER
git config --global user.email "[email protected]"
git config --global user.name "Damon Ulmi"

git add .
git status
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { GeoChartConfig } from '@/core/utils/config/reader/uuid-config-reader';
import { logger } from '@/core/utils/logger';

import { AbstractEventProcessor, BatchedPropagationLayerDataArrayByMap } from '@/api/event-processors/abstract-event-processor';
import { UIEventProcessor } from './ui-event-processor';

// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with UIEventProcessor vs UIState

Expand Down Expand Up @@ -120,9 +121,12 @@ export class GeochartEventProcessor extends AbstractEventProcessor {
});
});

// set store charts config
// Set store charts config
this.getGeochartState(mapId)?.setterActions.setGeochartCharts(chartData);

// If there is chart data, tab should not be hidden
if (Object.keys(chartData).length) UIEventProcessor.showTab(mapId, 'geochart');

// Log
logger.logInfo('Added GeoChart configs for layer paths:', layerPaths);
}
Expand All @@ -145,6 +149,9 @@ export class GeochartEventProcessor extends AbstractEventProcessor {
// Update the layer data array in the store
this.getGeochartState(mapId)!.setterActions.setGeochartCharts({ ...this.getGeochartState(mapId)?.geochartChartsConfig, ...toAdd });

// Make sure tab is not hidden
UIEventProcessor.showTab(mapId, 'geochart');

// Log
logger.logInfo('Added GeoChart configs for layer path:', layerPath);
}
Expand All @@ -171,6 +178,9 @@ export class GeochartEventProcessor extends AbstractEventProcessor {
// Update the layer data array in the store
this.getGeochartState(mapId)!.setterActions.setGeochartCharts({ ...chartConfigs });

// If there are no more geochart layers, hide tab
if (!Object.keys(this.getGeochartState(mapId)!.geochartChartsConfig).length) UIEventProcessor.hideTab(mapId, 'geochart');

// Log
logger.logInfo('Removed GeoChart configs for layer path:', layerPath);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,14 @@ export class MapEventProcessor extends AbstractEventProcessor {
}

/**
* Gets the ordered layer info.
* Gets map layer paths in order.
* @param {string} mapId - The map id
* @returns {TypeOrderedLayerInfo[]} The ordered layer info
* @returns {string[]} The ordered layer paths
*/
static getMapLayerOrder(mapId: string): TypeOrderedLayerInfo[] {
return this.getMapStateProtected(mapId).orderedLayerInfo;
static getMapLayerOrder(mapId: string): string[] {
return this.getMapStateProtected(mapId).orderedLayerInfo.map((orderedLayerInfo) => {
return orderedLayerInfo.layerPath;
});
}

static getMapState(mapId: string): TypeMapState {
Expand Down Expand Up @@ -453,6 +455,11 @@ export class MapEventProcessor extends AbstractEventProcessor {
// GV No need to save in the store, because this will trigger an event on MapViewer which will take care of updating the store
}

/**
* Gets the ordered layer info.
* @param {string} mapId - The map id
* @returns {TypeOrderedLayerInfo[]} The ordered layer info
*/
static getMapOrderedLayerInfo(mapId: string): TypeOrderedLayerInfo[] {
return this.getMapStateProtected(mapId).orderedLayerInfo;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { MapEventProcessor } from './map-event-processor';
import { AbstractGVVector } from '@/geo/layer/gv-layers/vector/abstract-gv-vector';
import { GVWMS } from '@/geo/layer/gv-layers/raster/gv-wms';
import { GVEsriImage } from '@/geo/layer/gv-layers/raster/gv-esri-image';
import { UIEventProcessor } from './ui-event-processor';

// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with UIEventProcessor vs UIState

Expand Down Expand Up @@ -85,6 +86,9 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor {

const { defaultValue, field, filtering, minAndMax, values } = timeSliderLayer[layerPath];
this.applyFilters(mapId, layerPath, defaultValue, field, filtering, minAndMax, values);

// Make sure tab is visible
UIEventProcessor.showTab(mapId, 'time-slider');
}

/**
Expand All @@ -95,6 +99,10 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor {
static removeTimeSliderLayer(mapId: string, layerPath: string): void {
// Redirect
this.getTimesliderState(mapId)?.setterActions.removeTimeSliderLayer(layerPath);

// If there are no layers with time dimension, hide tab
if (!this.getTimesliderState(mapId) || !Object.keys(this.getTimesliderState(mapId)!.timeSliderLayers).length)
UIEventProcessor.hideTab(mapId, 'time-slider');
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,26 @@ export class UIEventProcessor extends AbstractEventProcessor {
* @param {string} mapId The mapId
* @returns {IUIState} The UI state.
*/
protected static getUIState(mapId: string): IUIState {
protected static getUIStateProtected(mapId: string): IUIState {
// Return the time slider state
return super.getState(mapId).uiState;
}

// #region
static getActiveFooterBarTab(mapId: string): string {
return this.getUIState(mapId).activeFooterBarTabId;
return this.getUIStateProtected(mapId).activeFooterBarTabId;
}

static getAppBarComponents(mapId: string): TypeValidAppBarCoreProps[] {
return this.getUIState(mapId).appBarComponents;
return this.getUIStateProtected(mapId).appBarComponents;
}

static getCorePackageComponents(mapId: string): TypeMapCorePackages {
return this.getUIState(mapId).corePackagesComponents;
return this.getUIStateProtected(mapId).corePackagesComponents;
}

static getFooterBarIsCollapsed(mapId: string): boolean {
return this.getUIStateProtected(mapId).footerBarIsCollapsed;
}
// #endregion

Expand All @@ -41,15 +45,33 @@ export class UIEventProcessor extends AbstractEventProcessor {
// **********************************************************
// GV NEVER add a store action who does set state AND map action at a same time.
// GV Review the action in store state to make sure
static hideTab(mapId: string, tab: string): void {
if (!this.getUIStateProtected(mapId).hiddenTabs.includes(tab))
this.getUIStateProtected(mapId).setterActions.setHiddenTabs([...this.getUIStateProtected(mapId).hiddenTabs, tab]);
}

static showTab(mapId: string, tab: string): void {
const curHiddenTabs = this.getUIStateProtected(mapId).hiddenTabs;
const tabIndex = curHiddenTabs.indexOf(tab);
if (tabIndex !== -1) {
curHiddenTabs.splice(tabIndex, 1);
this.getUIStateProtected(mapId).setterActions.setHiddenTabs(curHiddenTabs);
}
}

static setActiveFooterBarTab(mapId: string, id: string): void {
this.getUIState(mapId).setterActions.setActiveFooterBarTab(id);
this.getUIStateProtected(mapId).setterActions.setActiveFooterBarTab(id);
}

static setActiveAppBarTab(mapId: string, tabId: string, tabGroup: string, isOpen: boolean): void {
this.getUIState(mapId).setterActions.setActiveAppBarTab(tabId, tabGroup, isOpen);
this.getUIStateProtected(mapId).setterActions.setActiveAppBarTab(tabId, tabGroup, isOpen);
}

static getActiveAppBarTab(mapId: string): ActiveAppBarTabType {
return this.getUIState(mapId).activeAppBarTab;
return this.getUIStateProtected(mapId).activeAppBarTab;
}

static setFooterBarIsCollapsed(mapId: string, collapsed: boolean): void {
this.getUIStateProtected(mapId).setterActions.setFooterBarIsCollapsed(collapsed);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ export function FooterBar(props: FooterBarProps): JSX.Element | null {
label: `${camelCase(tab)}.title`,
icon: allTabs[tab]?.icon ?? '',
content: allTabs[tab]?.content ?? '',
};
}) as unknown as TypeTabs[];
} as TypeTabs;
});
}, [memoTabs, tabsList]);

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/geoview-core/src/core/stores/state-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export class StateApi {
// Apply some ordering logic
const direction = move < 0 ? -1 : 1;
let absoluteMoves = Math.abs(move);
const orderedLayers = [...MapEventProcessor.getMapLayerOrder(this.mapId)];
const orderedLayers = [...MapEventProcessor.getMapOrderedLayerInfo(this.mapId)];
let startingIndex = -1;
for (let i = 0; i < orderedLayers.length; i++) if (orderedLayers[i].layerPath === layerPath) startingIndex = i;
const layerInfo = orderedLayers[startingIndex];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { TypeMapCorePackages, TypeNavBarProps, TypeValidAppBarCoreProps } from '
import { useGeoViewStore } from '@/core/stores/stores-managers';
import { TypeSetStore, TypeGetStore } from '@/core/stores/geoview-store';
import { TypeMapFeaturesConfig } from '@/core/types/global-types';
import { UIEventProcessor } from '@/api/event-processors/event-processor-children/ui-event-processor';

// GV Important: See notes in header of MapEventProcessor file for information on the paradigm to apply when working with UIEventProcessor vs UIState

Expand All @@ -23,6 +24,7 @@ export interface IUIState {
appBarComponents: TypeValidAppBarCoreProps[];
corePackagesComponents: TypeMapCorePackages;
focusITem: FocusItemProps;
hiddenTabs: string[];
mapInfoExpanded: boolean;
navBarComponents: TypeNavBarProps;
footerPanelResizeValue: number;
Expand All @@ -31,8 +33,10 @@ export interface IUIState {
setDefaultConfigValues: (geoviewConfig: TypeMapFeaturesConfig) => void;

actions: {
hideTab: (tab: string) => void;
closeModal: () => void;
openModal: (uiFocus: FocusItemProps) => void;
showTab: (tab: string) => void;
setActiveFooterBarTab: (id: string) => void;
setActiveAppBarTab: (tabId: string, tabGroup: string, isOpen: boolean) => void;
setActiveTrapGeoView: (active: boolean) => void;
Expand All @@ -48,6 +52,7 @@ export interface IUIState {
setActiveAppBarTab: (tabId: string, tabGroup: string, isOpen: boolean) => void;
setActiveTrapGeoView: (active: boolean) => void;
setFooterPanelResizeValue: (value: number) => void;
setHiddenTabs: (hiddenTabs: string[]) => void;
setMapInfoExpanded: (expanded: boolean) => void;
setFooterBarIsCollapsed: (collapsed: boolean) => void;
};
Expand All @@ -69,6 +74,7 @@ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIStat
activeTrapGeoView: false,
corePackagesComponents: [],
focusITem: { activeElementId: false, callbackElementId: false },
hiddenTabs: ['time-slider', 'geochart'],
mapInfoExpanded: false,
navBarComponents: [],
footerPanelResizeValue: 35,
Expand All @@ -90,6 +96,10 @@ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIStat
// #region ACTIONS

actions: {
hideTab: (tab: string): void => {
// Redirect to event processor
UIEventProcessor.hideTab(get().mapId, tab);
},
closeModal: () => {
// Redirect to setter
get().uiState.setterActions.closeModal();
Expand All @@ -98,6 +108,10 @@ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIStat
// Redirect to setter
get().uiState.setterActions.openModal(uiFocus);
},
showTab: (tab: string): void => {
// Redirect to event processor
UIEventProcessor.showTab(get().mapId, tab);
},
setActiveFooterBarTab: (id: string) => {
// Redirect to setter
get().uiState.setterActions.setActiveFooterBarTab(id);
Expand Down Expand Up @@ -158,6 +172,14 @@ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIStat
},
});
},
setHiddenTabs: (hiddenTabs: string[]) => {
set({
uiState: {
...get().uiState,
hiddenTabs: [...hiddenTabs],
},
});
},
setFooterPanelResizeValue: (value) => {
set({
uiState: {
Expand Down Expand Up @@ -220,6 +242,7 @@ export const useUICorePackagesComponents = (): TypeMapCorePackages =>
useStore(useGeoViewStore(), (state) => state.uiState.corePackagesComponents);
export const useUIFooterPanelResizeValue = (): number => useStore(useGeoViewStore(), (state) => state.uiState.footerPanelResizeValue);
export const useUIFooterPanelResizeValues = (): number[] => useStore(useGeoViewStore(), (state) => state.uiState.footerPanelResizeValues);
export const useUIHiddenTabs = (): string[] => useStore(useGeoViewStore(), (state) => state.uiState.hiddenTabs);
export const useUIMapInfoExpanded = (): boolean => useStore(useGeoViewStore(), (state) => state.uiState.mapInfoExpanded);
export const useUINavbarComponents = (): TypeNavBarProps => useStore(useGeoViewStore(), (state) => state.uiState.navBarComponents);
export const useUIFooterBarIsCollapsed = (): boolean => useStore(useGeoViewStore(), (state) => state.uiState.footerBarIsCollapsed);
Expand Down
12 changes: 6 additions & 6 deletions packages/geoview-core/src/geo/layer/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1395,17 +1395,17 @@ export class LayerApi {
*/
setOrToggleLayerVisibility(layerPath: string, newValue?: boolean): void {
// Apply some visibility logic
const curOrderedLayerInfo = MapEventProcessor.getMapLayerOrder(this.getMapId());
const curOrderedLayerInfo = MapEventProcessor.getMapOrderedLayerInfo(this.getMapId());
const layerVisibility = MapEventProcessor.getMapVisibilityFromOrderedLayerInfo(this.getMapId(), layerPath);
// Determine the outcome of the new visibility based on parameters
const newVisibility = newValue !== undefined ? newValue : !layerVisibility;
const layerInfos = curOrderedLayerInfo.filter((info: { layerPath: string }) => info.layerPath.startsWith(layerPath));
const layerInfos = curOrderedLayerInfo.filter((info: TypeOrderedLayerInfo) => info.layerPath.startsWith(layerPath));
const parentLayerPathArray = layerPath.split('/');
parentLayerPathArray.pop();
const parentLayerPath = parentLayerPathArray.join('/');
const parentLayerInfo = curOrderedLayerInfo.find((info: { layerPath: string }) => info.layerPath === parentLayerPath);
const parentLayerInfo = curOrderedLayerInfo.find((info: TypeOrderedLayerInfo) => info.layerPath === parentLayerPath);

layerInfos.forEach((layerInfo: { visible: boolean; layerPath: string }) => {
layerInfos.forEach((layerInfo: TypeOrderedLayerInfo) => {
if (layerInfo) {
// If the new visibility is different than before
if (newVisibility !== layerVisibility) {
Expand All @@ -1431,9 +1431,9 @@ export class LayerApi {
}
}
const children = curOrderedLayerInfo.filter(
(info: { layerPath: string }) => info.layerPath.startsWith(parentLayerPath) && info.layerPath !== parentLayerPath
(info: TypeOrderedLayerInfo) => info.layerPath.startsWith(parentLayerPath) && info.layerPath !== parentLayerPath
);
if (!children.some((child: { visible: boolean }) => child.visible === true)) {
if (!children.some((child: TypeOrderedLayerInfo) => child.visible === true)) {
this.setOrToggleLayerVisibility(parentLayerPath, false);

// Emit event
Expand Down
2 changes: 1 addition & 1 deletion packages/geoview-core/src/geo/map/map-viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ export class MapViewer {
* @returns {TypeOrderedLayerInfo[]} The ordered layer info
*/
getMapLayerOrderInfo(): TypeOrderedLayerInfo[] {
return MapEventProcessor.getMapLayerOrder(this.mapId);
return MapEventProcessor.getMapOrderedLayerInfo(this.mapId);
}

/**
Expand Down
13 changes: 11 additions & 2 deletions packages/geoview-core/src/ui/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ export function Button(props: ButtonProps): JSX.Element {
const theme = useTheme();
const mobileView = useMediaQuery(theme.breakpoints.down('md'));

return (
<Tooltip title={t(tooltip || '')} placement={tooltipPlacement || 'bottom'} TransitionComponent={Fade}>
function getMaterialButton(): JSX.Element {
return (
<MaterialButton
fullWidth={fullWidth}
id={id}
Expand All @@ -58,6 +58,15 @@ export function Button(props: ButtonProps): JSX.Element {
>
{!(makeResponsive && mobileView) ? children : null}
</MaterialButton>
);
}

if (disabled) {
return getMaterialButton();
}
return (
<Tooltip title={t((tooltip as string) || '') as string} placement={tooltipPlacement} TransitionComponent={Fade}>
{getMaterialButton()}
</Tooltip>
);
}
4 changes: 3 additions & 1 deletion packages/geoview-core/src/ui/tabs/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Select, TypeMenuItemProps } from '@/ui/select/select';
import { getSxClasses } from './tabs-style';
import { TabPanel } from './tab-panel';
import { useMapSize } from '@/core/stores/store-interface-and-intial-values/map-state';
import { useUIHiddenTabs } from '@/core/stores/store-interface-and-intial-values/ui-state';

/**
* Type used for properties of each tab
Expand Down Expand Up @@ -84,6 +85,7 @@ export function Tabs(props: TypeTabsProps): JSX.Element {

// get store values and actions
const mapSize = useMapSize();
const hiddenTabs = useUIHiddenTabs();

// show/hide dropdown based on map size
const initMobileDropdown = mapSize[0] !== 0 ? mapSize[0] < theme.breakpoints.values.sm : false;
Expand Down Expand Up @@ -197,7 +199,7 @@ export function Tabs(props: TypeTabsProps): JSX.Element {
iconPosition="start"
id={`tab-${index}`}
onClick={() => handleClick(index)}
sx={sxClasses.tab}
sx={hiddenTabs.includes(tab.id) ? { display: 'none' } : sxClasses.tab}
{...tabProps}
/>
);
Expand Down
Loading
Loading