diff --git a/.github/workflows/type-build.yml b/.github/workflows/type-build.yml index f3149f440d7..e28dd0cfc0b 100644 --- a/.github/workflows/type-build.yml +++ b/.github/workflows/type-build.yml @@ -44,7 +44,8 @@ jobs: rm -r common rm -r packages - git config --global user.name $USER + git config --global user.email "damon.ulmi@nrcan-rncan.gc.ca" + git config --global user.name "Damon Ulmi" git add . git status diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/geochart-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/geochart-event-processor.ts index 4601daead7e..b495ea7b064 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/geochart-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/geochart-event-processor.ts @@ -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 @@ -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.removeHiddenTab(mapId, 'geochart'); + // Log logger.logInfo('Added GeoChart configs for layer paths:', layerPaths); } @@ -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.removeHiddenTab(mapId, 'geochart'); + // Log logger.logInfo('Added GeoChart configs for layer path:', layerPath); } @@ -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.addHiddenTab(mapId, 'geochart'); + // Log logger.logInfo('Removed GeoChart configs for layer path:', layerPath); } diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts index 8f33e64bf78..c3d12934b9c 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/map-event-processor.ts @@ -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 { @@ -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; } diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/time-slider-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/time-slider-event-processor.ts index 90f7634e349..3f3967999eb 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/time-slider-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/time-slider-event-processor.ts @@ -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 @@ -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.removeHiddenTab(mapId, 'time-slider'); } /** @@ -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.addHiddenTab(mapId, 'time-slider'); } /** diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/ui-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/ui-event-processor.ts index dfa25c79ae2..7a4e4ec8f9f 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/ui-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/ui-event-processor.ts @@ -34,6 +34,10 @@ export class UIEventProcessor extends AbstractEventProcessor { static getCorePackageComponents(mapId: string): TypeMapCorePackages { return this.getUIState(mapId).corePackagesComponents; } + + static getFooterBarIsCollapsed(mapId: string): boolean { + return this.getUIState(mapId).footerBarIsCollapsed; + } // #endregion // ********************************************************** @@ -41,6 +45,20 @@ 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 addHiddenTab(mapId: string, tab: string): void { + if (!this.getUIState(mapId).hiddenTabs.includes(tab)) + this.getUIState(mapId).setterActions.setHiddenTabs([...this.getUIState(mapId).hiddenTabs, tab]); + } + + static removeHiddenTab(mapId: string, tab: string): void { + const curHiddenTabs = this.getUIState(mapId).hiddenTabs; + const tabIndex = curHiddenTabs.indexOf(tab); + if (tabIndex !== -1) { + curHiddenTabs.splice(tabIndex, 1); + this.getUIState(mapId).setterActions.setHiddenTabs(curHiddenTabs); + } + } + static setActiveFooterBarTab(mapId: string, id: string): void { this.getUIState(mapId).setterActions.setActiveFooterBarTab(id); } @@ -52,4 +70,8 @@ export class UIEventProcessor extends AbstractEventProcessor { static getActiveAppBarTab(mapId: string): ActiveAppBarTabType { return this.getUIState(mapId).activeAppBarTab; } + + static setFooterBarIsCollapsed(mapId: string, collapsed: boolean): void { + this.getUIState(mapId).setterActions.setFooterBarIsCollapsed(collapsed); + } } diff --git a/packages/geoview-core/src/core/components/footer-bar/footer-bar.tsx b/packages/geoview-core/src/core/components/footer-bar/footer-bar.tsx index 0e665e5eae4..4ab01d15318 100644 --- a/packages/geoview-core/src/core/components/footer-bar/footer-bar.tsx +++ b/packages/geoview-core/src/core/components/footer-bar/footer-bar.tsx @@ -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]); /** diff --git a/packages/geoview-core/src/core/stores/state-api.ts b/packages/geoview-core/src/core/stores/state-api.ts index 935c34b046e..0ced1c749e9 100644 --- a/packages/geoview-core/src/core/stores/state-api.ts +++ b/packages/geoview-core/src/core/stores/state-api.ts @@ -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]; diff --git a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/ui-state.ts b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/ui-state.ts index ce2f08e4fd9..f72eb236482 100644 --- a/packages/geoview-core/src/core/stores/store-interface-and-intial-values/ui-state.ts +++ b/packages/geoview-core/src/core/stores/store-interface-and-intial-values/ui-state.ts @@ -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 @@ -23,6 +24,7 @@ export interface IUIState { appBarComponents: TypeValidAppBarCoreProps[]; corePackagesComponents: TypeMapCorePackages; focusITem: FocusItemProps; + hiddenTabs: string[]; mapInfoExpanded: boolean; navBarComponents: TypeNavBarProps; footerPanelResizeValue: number; @@ -31,8 +33,10 @@ export interface IUIState { setDefaultConfigValues: (geoviewConfig: TypeMapFeaturesConfig) => void; actions: { + addHiddenTab: (tab: string) => void; closeModal: () => void; openModal: (uiFocus: FocusItemProps) => void; + removeHiddenTab: (tab: string) => void; setActiveFooterBarTab: (id: string) => void; setActiveAppBarTab: (tabId: string, tabGroup: string, isOpen: boolean) => void; setActiveTrapGeoView: (active: boolean) => void; @@ -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; }; @@ -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, @@ -90,6 +96,10 @@ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIStat // #region ACTIONS actions: { + addHiddenTab: (tab: string): void => { + // Redirect to event processor + UIEventProcessor.addHiddenTab(get().mapId, tab); + }, closeModal: () => { // Redirect to setter get().uiState.setterActions.closeModal(); @@ -98,6 +108,10 @@ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIStat // Redirect to setter get().uiState.setterActions.openModal(uiFocus); }, + removeHiddenTab: (tab: string): void => { + // Redirect to event processor + UIEventProcessor.removeHiddenTab(get().mapId, tab); + }, setActiveFooterBarTab: (id: string) => { // Redirect to setter get().uiState.setterActions.setActiveFooterBarTab(id); @@ -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: { @@ -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); diff --git a/packages/geoview-core/src/geo/map/map-viewer.ts b/packages/geoview-core/src/geo/map/map-viewer.ts index 9f6bfc0d97b..f5cef27a7fc 100644 --- a/packages/geoview-core/src/geo/map/map-viewer.ts +++ b/packages/geoview-core/src/geo/map/map-viewer.ts @@ -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); } /** diff --git a/packages/geoview-core/src/ui/button/button.tsx b/packages/geoview-core/src/ui/button/button.tsx index 88830b7d01c..9b6dc78a714 100644 --- a/packages/geoview-core/src/ui/button/button.tsx +++ b/packages/geoview-core/src/ui/button/button.tsx @@ -42,22 +42,24 @@ export function Button(props: ButtonProps): JSX.Element { return ( - - {!(makeResponsive && mobileView) ? children : null} - + + + {!(makeResponsive && mobileView) ? children : null} + + ); } diff --git a/packages/geoview-core/src/ui/icon-button/icon-button.tsx b/packages/geoview-core/src/ui/icon-button/icon-button.tsx index 6dcbfa7f29b..f687538e28e 100644 --- a/packages/geoview-core/src/ui/icon-button/icon-button.tsx +++ b/packages/geoview-core/src/ui/icon-button/icon-button.tsx @@ -32,21 +32,23 @@ export function IconButton(props: TypeIconButtonProps): JSX.Element { function getMaterialIconButton(): JSX.Element { return ( - - {children && children} - + + + {children && children} + + ); } diff --git a/packages/geoview-core/src/ui/tabs/tabs.tsx b/packages/geoview-core/src/ui/tabs/tabs.tsx index 4f6d8ef2caf..e22faf3e1da 100644 --- a/packages/geoview-core/src/ui/tabs/tabs.tsx +++ b/packages/geoview-core/src/ui/tabs/tabs.tsx @@ -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 @@ -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; @@ -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} /> );