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

fix(UI): refactor appbar component #closes2145 #2147

Merged
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,13 @@ export class FeatureInfoEventProcessor extends AbstractEventProcessor {
// If there was some features on this propagation
if (atLeastOneFeature) {
// If the current tab is not 'details' nor 'geochart', switch to details
if (!['details', 'geochart'].includes(UIEventProcessor.getActiveFooterBarTab(mapId)))
if (!['details', 'geochart'].includes(UIEventProcessor.getActiveFooterBarTab(mapId))) {
UIEventProcessor.setActiveFooterBarTab(mapId, 'details');
}

if (UIEventProcessor.getActiveAppBarPanelId(mapId) !== 'AppbarPanelButtonDetails') {
UIEventProcessor.setActiveAppBarPanelId(mapId, 'AppbarPanelButtonDetails');
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export class UIEventProcessor extends AbstractEventProcessor {
return this.getUIState(mapId).activeFooterBarTabId;
}

static getActiveAppBarPanelId(mapId: string): string {
return this.getUIState(mapId).activeAppBarPanelId;
}

static getAppBarComponents(mapId: string): TypeValidAppBarCoreProps {
return this.getUIState(mapId).appBarComponents;
}
Expand All @@ -56,4 +60,8 @@ export class UIEventProcessor extends AbstractEventProcessor {
static setActiveFooterBarTab(mapId: string, id: string): void {
this.getUIState(mapId).setterActions.setActiveFooterBarTab(id);
}

static setActiveAppBarPanelId(mapId: string, id: string): void {
this.getUIState(mapId).setterActions.setActiveAppBarPanelId(id);
}
}
60 changes: 36 additions & 24 deletions packages/geoview-core/src/core/components/app-bar/app-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { Plugin } from '@/api/plugin/plugin';
import { TypeButtonPanel, TypePanelProps } from '@/ui/panel/panel-types';
import ExportButton from '@/core/components/export/export-modal-button';
import {
useUIActiveAppBarPanelId,
useUIActiveFocusItem,
useUIActiveFooterBarTabId,
useUIAppbarComponents,
useUIAppbarGeolocatorActive,
useUIStoreActions,
Expand Down Expand Up @@ -47,6 +47,8 @@ export function AppBar(props: AppBarProps): JSX.Element {

const { api: appBarApi } = props;

const appBarTabRefs = useRef(['legend', 'details', 'guide']);

const mapId = useGeoViewMapId();

const { t } = useTranslation();
Expand All @@ -56,19 +58,17 @@ export function AppBar(props: AppBarProps): JSX.Element {

// internal component state
const [buttonPanelGroups, setButtonPanelGroups] = useState<Record<string, Record<string, TypeButtonPanel>>>({});
const [selectedAppBarButtonId, setSelectedAppbarButtonId] = useState<string>('');
const appBar = useRef<HTMLDivElement>(null);

// get store values and action
const activeModalId = useUIActiveFocusItem().activeElementId;
const interaction = useMapInteraction();
const appBarComponents = useUIAppbarComponents();
const { hideClickMarker } = useMapStoreActions();
const activeAppBarPanelId = useUIActiveAppBarPanelId();
const geoviewElement = useAppGeoviewHTMLElement().querySelector('[id^="mapTargetElement-"]') as HTMLElement;
// TODO: remove active footerTab Id and create new one for AppBar id.
const activeFooterTabId = useUIActiveFooterBarTabId();

const { setGeolocatorActive } = useUIStoreActions();
const { setGeolocatorActive, setActiveAppBarPanelId } = useUIStoreActions();
const isGeolocatorActive = useUIAppbarGeolocatorActive();

// get store config for app bar to add (similar logic as in footer-bar)
Expand Down Expand Up @@ -106,9 +106,9 @@ export function AppBar(props: AppBarProps): JSX.Element {

// Redirect to helper
helpClosePanelById(mapId, buttonPanelGroups, buttonId, groupName, setButtonPanelGroups, focusWhenNoElementCallback);
setSelectedAppbarButtonId('');
setActiveAppBarPanelId('');
},
[buttonPanelGroups, geoviewElement, mapId]
[buttonPanelGroups, geoviewElement, mapId, setActiveAppBarPanelId]
);

const closeAll = useCallback(() => {
Expand All @@ -126,9 +126,9 @@ export function AppBar(props: AppBarProps): JSX.Element {

// Redirect to helper
helpOpenPanelById(buttonPanelGroups, buttonId, groupName, setButtonPanelGroups, closeAll);
setSelectedAppbarButtonId(buttonId);
setActiveAppBarPanelId(buttonId);
},
[buttonPanelGroups, closeAll]
[buttonPanelGroups, closeAll, setActiveAppBarPanelId]
);

const handleButtonClicked = useCallback(
Expand Down Expand Up @@ -157,11 +157,11 @@ export function AppBar(props: AppBarProps): JSX.Element {

const handleGeneralCloseClicked = useCallback(() => {
// Log
logger.logTraceUseCallback('APP-BAR - handleGeneralCloseClicked', selectedAppBarButtonId);
logger.logTraceUseCallback('APP-BAR - handleGeneralCloseClicked', activeAppBarPanelId);

// Close it
closePanelById(selectedAppBarButtonId, undefined);
}, [selectedAppBarButtonId, closePanelById]);
closePanelById(activeAppBarPanelId, undefined);
}, [activeAppBarPanelId, closePanelById]);

const handleAddButtonPanel = useCallback(
(sender: AppBarApi, event: AppBarCreatedEvent) => {
Expand Down Expand Up @@ -218,9 +218,8 @@ export function AppBar(props: AppBarProps): JSX.Element {
useEffect(() => {
// Log
logger.logTraceUseEffect('APP-BAR - open detail panel when clicked on map', mapId);
// TODO: remove active footerTab Id and create new one for AppBar id.
// open AppBar detail drawer when click on map.
if (activeFooterTabId === 'details' && buttonPanelGroups?.details?.AppbarPanelButtonDetails?.panel) {
if (activeAppBarPanelId === 'AppbarPanelButtonDetails' && buttonPanelGroups?.details?.AppbarPanelButtonDetails?.panel) {
// close geolocator when user click on map layer.
if (isGeolocatorActive) {
setGeolocatorActive(false);
Expand All @@ -229,7 +228,7 @@ export function AppBar(props: AppBarProps): JSX.Element {
openPanelById(buttonPanelGroups?.details?.AppbarPanelButtonDetails?.button?.id || '', undefined);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeFooterTabId]);
}, [activeAppBarPanelId]);

/**
* Create default tabs from configuration parameters (similar logic as in footer-bar).
Expand Down Expand Up @@ -268,7 +267,7 @@ export function AppBar(props: AppBarProps): JSX.Element {

// render footer bar tabs
(appBarConfig?.tabs.core ?? [])
.filter((tab) => tab === 'guide' || tab === 'details' || tab === 'legend')
.filter((tab) => appBarTabRefs.current.includes(tab))
.map((tab): [TypeIconButtonProps, TypePanelProps, string] => {
const button: TypeIconButtonProps = {
id: `AppbarPanelButton${capitalize(tab)}`,
Expand All @@ -290,16 +289,29 @@ export function AppBar(props: AppBarProps): JSX.Element {
return [button, panel, tab];
})
.forEach((footerGroup) => appBarApi.createAppbarPanel(footerGroup[0], footerGroup[1], footerGroup[2]));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [appBarConfig?.tabs.core, appBarApi]); // Not exhaustive, because it'd be dangerous to trigger on `panels` or on `t`, because of how the AppBar panels are just recreated all the time (should refactor this, maybe..)
}, [appBarConfig?.tabs.core, appBarApi, t, memoPanels]);

// #endregion

let buttonPanelGroupNames = Object.keys(buttonPanelGroups);
buttonPanelGroupNames = enforceArrayOrder(buttonPanelGroupNames, ['legend', 'details', 'guide']);
const topGroupNames = buttonPanelGroupNames.filter((groupName) => groupName !== 'guide');
const bottomGroupNames = buttonPanelGroupNames.filter((groupName) => groupName === 'guide');
/**
* Re-order the footer tab buttons.
*/
const { topGroupNames, bottomGroupNames } = useMemo(() => {
// Log
logger.logTraceUseMemo('APP-BAR - panels');

let buttonPanelGroupNames = Object.keys(buttonPanelGroups);
buttonPanelGroupNames = enforceArrayOrder(buttonPanelGroupNames, appBarTabRefs.current);
const topGroup = buttonPanelGroupNames.filter((groupName) => groupName !== 'guide');
const bottomGroup = buttonPanelGroupNames.filter((groupName) => groupName === 'guide');
return { topGroupNames: topGroup, bottomGroupNames: bottomGroup };
}, [buttonPanelGroups]);

/**
* Render Tab groups in appbar.
* @param {string[]} groupNames group that will be rendered in appbar.
* @returns JSX.Element
*/
const renderButtonGroup = (groupNames: string[]): ReactNode => {
return (
<>
Expand All @@ -320,9 +332,9 @@ export function AppBar(props: AppBarProps): JSX.Element {
aria-label={buttonPanel.button.tooltip}
tooltip={buttonPanel.button.tooltip}
tooltipPlacement="right"
className={`style3 ${selectedAppBarButtonId === buttonPanel.button.id ? 'active' : ''}`}
className={`style3 ${activeAppBarPanelId === buttonPanel.button.id ? 'active' : ''}`}
size="small"
onClick={(): void => handleButtonClicked(buttonPanel.button.id!, groupName)}
onClick={() => handleButtonClicked(buttonPanel.button.id!, groupName)}
>
{buttonPanel.button.children}
</IconButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type FocusItemProps = {
export interface IUIState {
activeFooterBarTabId: string;
activeTrapGeoView: boolean;
activeAppBarPanelId: string;
appBarComponents: TypeValidAppBarCoreProps;
corePackagesComponents: TypeMapCorePackages;
focusITem: FocusItemProps;
Expand All @@ -29,6 +30,7 @@ export interface IUIState {
closeModal: () => void;
openModal: (uiFocus: FocusItemProps) => void;
setActiveFooterBarTab: (id: string) => void;
setActiveAppBarPanelId: (id: string) => void;
setActiveTrapGeoView: (active: boolean) => void;
setGeolocatorActive: (active: boolean) => void;
setFooterPanelResizeValue: (value: number) => void;
Expand All @@ -40,6 +42,7 @@ export interface IUIState {
closeModal: () => void;
openModal: (uiFocus: FocusItemProps) => void;
setActiveFooterBarTab: (id: string) => void;
setActiveAppBarPanelId: (id: string) => void;
setActiveTrapGeoView: (active: boolean) => void;
setGeolocatorActive: (active: boolean) => void;
setFooterPanelResizeValue: (value: number) => void;
Expand All @@ -52,6 +55,7 @@ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIStat
const init = {
appBarComponents: ['geolocator'],
activeFooterBarTabId: 'legend',
activeAppBarPanelId: '',
activeTrapGeoView: false,
corePackagesComponents: [],
focusITem: { activeElementId: false, callbackElementId: false },
Expand Down Expand Up @@ -87,6 +91,10 @@ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIStat
// Redirect to setter
get().uiState.setterActions.setActiveFooterBarTab(id);
},
setActiveAppBarPanelId: (id: string) => {
// Redirect to setter
get().uiState.setterActions.setActiveAppBarPanelId(id);
},
setActiveTrapGeoView: (active: boolean) => {
// Redirect to setter
get().uiState.setterActions.setActiveTrapGeoView(active);
Expand Down Expand Up @@ -135,6 +143,14 @@ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIStat
},
});
},
setActiveAppBarPanelId: (id: string) => {
set({
uiState: {
...get().uiState,
activeAppBarPanelId: id,
},
});
},
setActiveTrapGeoView: (active: boolean) => {
set({
uiState: {
Expand Down Expand Up @@ -187,6 +203,7 @@ export function initializeUIState(set: TypeSetStore, get: TypeGetStore): IUIStat
// **********************************************************
export const useUIActiveFocusItem = (): FocusItemProps => useStore(useGeoViewStore(), (state) => state.uiState.focusITem);
export const useUIActiveFooterBarTabId = (): string => useStore(useGeoViewStore(), (state) => state.uiState.activeFooterBarTabId);
export const useUIActiveAppBarPanelId = (): string => useStore(useGeoViewStore(), (state) => state.uiState.activeAppBarPanelId);
export const useUIActiveTrapGeoView = (): boolean => useStore(useGeoViewStore(), (state) => state.uiState.activeTrapGeoView);
export const useUIAppbarComponents = (): TypeValidAppBarCoreProps => useStore(useGeoViewStore(), (state) => state.uiState.appBarComponents);
export const useUIAppbarGeolocatorActive = (): boolean => useStore(useGeoViewStore(), (state) => state.uiState.geoLocatorActive);
Expand Down
Loading