Skip to content

Commit

Permalink
fix(focus): Solve 2 click before map drag and simplify focus map/foot…
Browse files Browse the repository at this point in the history
…er (#2554)

* fix(focus): Solve 2 click before map drag and simplify focus map/footer
Closes #2551

* fix comments about autoscroll

* Fix tabs collapse and auto scroll

* fix comments

---------

Co-authored-by: jolevesq <[email protected]>
  • Loading branch information
jolevesq and jolevesq authored Oct 17, 2024
1 parent 858ca74 commit 7438da9
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 77 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 20 additions & 19 deletions packages/geoview-core/public/locales/en/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,17 +163,17 @@ Click on the **Download** button at the bottom to get the final generated map im
=1!footerPanel=

# Footer Bar

<a id="footerSection"></a>
The _Footer Bar_ appears below the map. The _Footer Bar_ can be expanded or collapsed by clicking on a tab in the _Footer Bar_ menu bar. To collapse the panel, simply click again on the active tab.

The _Footer Bar_ menu bar has the following tabs:

- Legend
- Layers
- Details
- Data Table
- Time Slider
- Chart
- [Legend](#legendSection)
- [Layers](#layersSection)
- [Details](#detailsSection)
- [Data Table](#dataTableSection)
- [Time Slider](#timeSliderSection)
- [Chart](#chartSection)
- Guide

_Depending on viewer configuration some tabs may not be available_
Expand All @@ -182,8 +182,8 @@ _Note: Some tabs in the Footer Bar are also available as tools in the Side Bar,

<br>
=2!legend=

### ![]({{assetsURL}}/img/guide/sidebar/legend_25.svg) Legend
<a id="legendSection"></a>
### ![]({{assetsURL}}/img/guide/sidebar/legend_25.svg) Legend [Top](#footerSection)

The _Legend_ tab displays the symbology associated with the layers displayed on the map.

Expand All @@ -195,8 +195,8 @@ The symbology for the layer can be toggled open and closed which is expanded ben

<br>
=2!layers=

### ![]({{assetsURL}}/img/guide/footer/layers_30.svg) Layers
<a id="layersSection"></a>
### ![]({{assetsURL}}/img/guide/footer/layers_30.svg) Layers [Top](#footerSection)

The _Layers_ tab has the following submenu options:

Expand Down Expand Up @@ -294,8 +294,8 @@ To remove a layer, click on the delete icon ![]({{assetsURL}}/img/guide/layers/r

<br>
=2!details=

### ![]({{assetsURL}}/img/guide/sidebar/details_30.svg) Details
<a id="detailsSection"></a>
### ![]({{assetsURL}}/img/guide/sidebar/details_30.svg) Details [Top](#footerSection)

The **Details** tab has two sections. The available layers for the map are listed in the left section, and the feature details for each layer are displayed in the right section.

Expand All @@ -313,8 +313,8 @@ Check the highlight box ![]({{assetsURL}}/img/guide/layers/check.png) to keep th

<br>
=2!dataTable=

### ![]({{assetsURL}}/img/guide/footer/data_table.svg) Data Table
<a id="dataTableSection"></a>
### ![]({{assetsURL}}/img/guide/footer/data_table.svg) Data Table [Top](#footerSection)

The **Data Table** tab has two sections. The layers are listed on the left and the layer data on the right. Click on a layer to show the layer data in the table on the right.

Expand All @@ -326,6 +326,7 @@ _Note: Some options may not be available or are preselected depending on various

| Symbol | Name | Description |
| ------------------------------------------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| <img src="{{assetsURL}}/img/guide/datatable/filters_clear.svg" width="30"/> | Clear Filters | Clear all data table filters |
| <img src="{{assetsURL}}/img/guide/datatable/filter_toggle.svg" width="30"/> | Display Filters | Toggle to show or hide filters |
| <img src="{{assetsURL}}/img/guide/datatable/filter.png" width="30"/> | Filter switch | Apply filters to the map |
| <img src="{{assetsURL}}/img/guide/datatable/column_show.svg" width="30"/> | Display Columns | Allows you to choose which columns you want visible and to pin columns to the left or right of the table |
Expand Down Expand Up @@ -394,8 +395,8 @@ To access the buttons and/or input fields within a cell, make sure the cell is h

<br>
=2!timeSlider=

### ![]({{assetsURL}}/img/guide/footer/time_slider_30.svg) Time Slider
<a id="timeSliderSection"></a>
### ![]({{assetsURL}}/img/guide/footer/time_slider_30.svg) Time Slider [Top](#footerSection)

The Time Slider tab on the Footer Bar has two sections. Layers with a time dimension are listed in the left section. Click on a layer to display its Time Slider in the right section:

Expand All @@ -415,8 +416,8 @@ The field being filtered on is displayed in the lower left of the Time Slider se

<br>
=2!chart=

### ![]({{assetsURL}}/img/guide/footer/chart_30.svg) Chart
<a id="chartSection"></a>
### ![]({{assetsURL}}/img/guide/footer/chart_30.svg) Chart [Top](#footerSection)

The Chart tab on the Footer Bar has two sections. Layers with a chart are listed in the left section. Select a feature on the map to display its chart in the right section.

Expand Down
2 changes: 0 additions & 2 deletions packages/geoview-core/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,6 @@
"errorMessage": "Sorry, unable to find the help document!"
},
"footerBar": {
"focusToMap": "Focus to map",
"focusToFooter": "Focus to footer",
"resizeTooltip": "Resize",
"noTab": "No tab"
}
Expand Down
33 changes: 20 additions & 13 deletions packages/geoview-core/public/locales/fr/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,17 +157,17 @@ Cliquez sur le bouton **Télécharger** au bas de la fenêtre pour générer l
=1!footerPanel=

# Pied de page

<a id="footerSection"></a>
Le _pied de page_ se trouve sous la carte. Vous pouvez le développer en cliquant sur un des onglets de son menu. Pour le réduire, vous n’avez qu’à recliquer sur l’onglet actif.

Le menu du _pied de page_ se compose des onglets suivants&nbsp;:

- Légende
- Couches
- Détails
- Données
- Curseur temporel
- Graphique
- [Légende](#legendSection)
- [Couches](#layersSection)
- [Détails](#detailsSection)
- [Données](#dataTableSection)
- [Curseur temporel](#timeSliderSection)
- [Graphique](#chartSection)
- Guide

_Selon la configuration du visualiseur, il se pourrait que certains onglets ne s’affichent pas._
Expand All @@ -176,7 +176,8 @@ _N.B.&nbsp;: Certains onglets du pied de page sont aussi accessibles comme outil

<br>
=2!legend=
### ![]({{assetsURL}}/img/guide/sidebar/legend_25.svg) Légende
<a id="legendSection"></a>
### ![]({{assetsURL}}/img/guide/sidebar/legend_25.svg) Légende [Haut de page](#footerSection)

L’onglet **Légende** présente les symboles des couches affichées sur la carte.

Expand All @@ -188,7 +189,8 @@ Vous pouvez développer ou réduire la liste des symboles d’une couche sous so

<br>
=2!layers=
### ![]({{assetsURL}}/img/guide/footer/layers_30.svg) Couches
<a id="layersSection"></a>
### ![]({{assetsURL}}/img/guide/footer/layers_30.svg) Couches [Haut de page](#footerSection)

L’onglet **Couches** comprend les sous-menus suivants&nbsp;:

Expand Down Expand Up @@ -286,7 +288,8 @@ Pour retirer une couche, cliquez sur l’icône de suppression ![]({{assetsURL}}

<br>
=2!details=
### ![]({{assetsURL}}/img/guide/sidebar/details_30.svg) Détails
<a id="detailsSection"></a>
### ![]({{assetsURL}}/img/guide/sidebar/details_30.svg) Détails [Haut de page](#footerSection)

L’onglet **Détails** se divise en deux sections. La section de gauche dresse la liste des couches accessibles, tandis que celle de droite affiche le détail des éléments pour chaque couche.

Expand All @@ -304,7 +307,8 @@ Cochez la case ![]({{assetsURL}}/img/guide/layers/check.png) pour garder l’él

<br>
=2!dataTable=
### ![]({{assetsURL}}/img/guide/footer/data_table.svg) Données
<a id="dataTableSection"></a>
### ![]({{assetsURL}}/img/guide/footer/data_table.svg) Données [Haut de page](#footerSection)

L’onglet **Données** se divise en deux sections. La liste des couches se trouve à gauche, et les données des couches, à droite. Cliquez sur une couche pour en voir les données dans le tableau de droite.

Expand All @@ -316,6 +320,7 @@ _N.B.&nbsp;: Selon différents facteurs, certaines options sont désactivées ou

| Symbole| Nom| Description|
|----------|----------|----------|
| <img src="{{assetsURL}}/img/guide/datatable/filters_clear.svg" width="30"/> | Effacer les filters | Effacer tout les filtres de la table.|
| <img src="{{assetsURL}}/img/guide/datatable/filter_toggle.svg" width="30"/>| Afficher/masquer les filtres| Basculer entre l’affichage et le masquage des filtres.|
| <img src="{{assetsURL}}/img/guide/datatable/filter.png" width="30"/>| Interrupteur de filtres| Appliquer les filtres à la carte.|
| <img src="{{assetsURL}}/img/guide/datatable/column_show.svg" width="30"/>| Afficher/masquer les colonnes| Choisir les colonnes visibles et épingler des colonnes à gauche ou à droite du tableau.|
Expand Down Expand Up @@ -384,7 +389,8 @@ Pour accéder aux boutons ou aux champs de saisie d’une cellule, assurez-vous

<br>
=2!timeSlider=
### ![]({{assetsURL}}/img/guide/footer/time_slider_30.svg) Curseur temporel
<a id="timeSliderSection"></a>
### ![]({{assetsURL}}/img/guide/footer/time_slider_30.svg) Curseur temporel [Haut de page](#footerSection)

L’onglet **Curseur temporel** dans le pied de page se divise en deux sections. La liste des couches ayant un facteur temporel se trouve dans la section de gauche. Cliquez sur une couche pour afficher son curseur temporel dans la section de droite&nbsp;:

Expand All @@ -404,7 +410,8 @@ Le champ visé par le filtre s’affiche en bas à gauche de la section du curse

<br>
=2!chart=
### ![]({{assetsURL}}/img/guide/footer/chart_30.svg) Graphique
<a id="chartSection"></a>
### ![]({{assetsURL}}/img/guide/footer/chart_30.svg) Graphique [Haut de page](#footerSection)

L’onglet **Graphique** dans le pied de page se divise en deux sections. La liste des couches comportant un graphique se trouve dans la section de gauche. Sélectionnez un élément sur la carte pour en voir le graphique dans la section de droite.

Expand Down
2 changes: 0 additions & 2 deletions packages/geoview-core/public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,6 @@
"errorMessage": "Désolé, impossible de trouver le document d'aide!"
},
"footerBar": {
"focusToMap": "Aller à la carte",
"focusToFooter": "Aller au pied de page",
"resizeTooltip": "Redimensionner",
"noTab": "Pas d'onglet"
}
Expand Down
45 changes: 18 additions & 27 deletions packages/geoview-core/src/core/components/footer-bar/footer-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { MutableRefObject, ReactNode, useCallback, useEffect, useMemo, useRef, u
import { camelCase } from 'lodash';
import { useTheme } from '@mui/material/styles';

import { Box, IconButton, Tabs, TypeTabs, MoveDownRoundedIcon, MoveUpRoundedIcon } from '@/ui';
import { Box, Tabs, TypeTabs } from '@/ui';
import { Plugin } from '@/api/plugin/plugin';
import { getSxClasses } from './footer-bar-style';
import { ResizeFooterPanel } from '@/core/components/resize-footer-panel/resize-footer-panel';
Expand Down Expand Up @@ -33,6 +33,7 @@ import { GuidePanel } from '@/core/components/guide/guide-panel';
import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor';
import { TypeRecordOfPlugin } from '@/api/plugin/plugin-types';
import { CONTAINER_TYPE } from '@/core/utils/constant';
import { isElementInViewport } from '@/core/utils/utilities';

interface Tab {
icon: ReactNode;
Expand All @@ -59,8 +60,6 @@ export function FooterBar(props: FooterBarProps): JSX.Element | null {
const theme = useTheme();
const sxClasses = getSxClasses(theme);

const [isFocusToMap, setIsFocusToMap] = useState<boolean>(true);

const tabsContainerRef = useRef<HTMLDivElement>();

// get store values and actions
Expand Down Expand Up @@ -350,16 +349,22 @@ export function FooterBar(props: FooterBarProps): JSX.Element | null {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [footerBarTabsConfig, mapId]);

// Handle focus using dynamic focus button
const handleDynamicFocus = useCallback((): void => {
// Scroll the footer into view on mouse click
useEffect((): void => {
// Log
logger.logTraceUseCallback('FOOTER BAR - handleDynamicFocus', isFocusToMap, mapId);

const shell = document.getElementById(`shell-${mapId}`);
const block = isFocusToMap ? 'start' : 'end';
shell?.scrollIntoView({ behavior: 'smooth', block });
setIsFocusToMap(!isFocusToMap);
}, [isFocusToMap, mapId]);
logger.logTraceUseEffect('FOOTER BAR - scrollIntoViewListener');

if (tabsContainerRef && tabsContainerRef.current) {
const header = tabsContainerRef.current.querySelector('#footerbar-header');
header?.addEventListener('click', () => {
// Register mouse interaction events (click). If element not in viewport, scroll the footer into view
if (!isElementInViewport(tabsContainerRef.current!)) {
const behaviorScroll = (window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'instant' : 'smooth') as ScrollBehavior;
tabsContainerRef.current?.scrollIntoView({ behavior: behaviorScroll as ScrollBehavior, block: 'center' });
}
});
}
}, [tabsContainerRef]);

return memoFooterBarTabs.length > 0 ? (
<Box
Expand All @@ -381,21 +386,7 @@ export function FooterBar(props: FooterBarProps): JSX.Element | null {
tabs={memoFooterBarTabs}
TabContentVisibilty={!isCollapsed ? 'visible' : 'hidden'}
containerType={CONTAINER_TYPE.FOOTER_BAR}
rightButtons={
<>
{!isCollapsed && isMapFullScreen && <ResizeFooterPanel />}
<IconButton
onClick={handleDynamicFocus}
tooltip={isFocusToMap ? 'footerBar.focusToMap' : 'footerBar.focusToFooter'}
className="buttonFilled"
disabled={
isCollapsed || isMapFullScreen || footerPanelResizeValues[footerPanelResizeValues.length - 1] === footerPanelResizeValue
}
>
{isFocusToMap ? <MoveUpRoundedIcon /> : <MoveDownRoundedIcon />}
</IconButton>
</>
}
rightButtons={!isCollapsed && isMapFullScreen && <ResizeFooterPanel />}
/>
</Box>
) : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,14 @@ export const getShellSxClasses = (theme: Theme): any => ({
},
},
shell: {
scrollMarginTop: '20px',
display: 'flex',
flexDirection: 'column',
top: theme.spacing(0),
right: theme.spacing(0),
left: theme.spacing(0),
bottom: theme.spacing(0),
overflow: 'hidden',
overflow: 'clip',
zIndex: 0,
height: '100%',
},
Expand Down
16 changes: 16 additions & 0 deletions packages/geoview-core/src/core/utils/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -560,3 +560,19 @@ export function handleEscapeKey(key: string, callbackId: string, isFocusTrapped?
cb?.();
}
}

/**
* Check if elemetn is in viewport
* @param {Element} el - The element to check for
* @returns {Boolean} true if visible, false otherwise
*/
export function isElementInViewport(el: Element): boolean {
const rect = el.getBoundingClientRect();

return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
24 changes: 15 additions & 9 deletions packages/geoview-core/src/geo/map/map-viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import { Snap } from '@/geo/interaction/snap';
import { Translate } from '@/geo/interaction/translate';
import EventHelper, { EventDelegateBase } from '@/api/events/event-helper';
import { ModalApi } from '@/ui';
import { delay, generateId, getLocalizedMessage } from '@/core/utils/utilities';
import { delay, generateId, getLocalizedMessage, isElementInViewport } from '@/core/utils/utilities';
import { createEmptyBasemap } from '@/geo/utils/utilities';
import { logger } from '@/core/utils/logger';
import { NORTH_POLE_POSITION } from '@/core/utils/constant';
Expand Down Expand Up @@ -572,19 +572,25 @@ export class MapViewer {
this.map.on('change:size', this.#handleMapChangeSize.bind(this));
this.map.dispatchEvent('change:size'); // dispatch event to set initial value

// Register mouse interaction events
// set autofocus/blur on mouse enter/leave the map so user can scroll (zoom) without having to click the map
// Register mouse interaction events. On mouse enter or leave, focus or blur the map container
const mapHTMLElement = this.map.getTargetElement();
mapHTMLElement.addEventListener('wheel', (event: WheelEvent) => {
event.preventDefault(); // Abort event
mapHTMLElement.focus();
mapHTMLElement.addEventListener('mouseenter', () => {
mapHTMLElement.focus({ preventScroll: true });
});

// eslint-disable-next-line @typescript-eslint/no-unused-vars
mapHTMLElement.addEventListener('mouseleave', (event: MouseEvent) => {
mapHTMLElement.addEventListener('mouseleave', () => {
mapHTMLElement.blur();
});

// Register mouse interaction events (wheel). If element not in viewport, scroll the map into view
const myScrollIntoViewEvent = (): void => {
if (!isElementInViewport(mapHTMLElement)) {
const behaviorScroll = (window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'instant' : 'smooth') as ScrollBehavior;
const shell = document.getElementById(`shell-${this.mapId}`);
shell?.scrollIntoView({ behavior: behaviorScroll as ScrollBehavior, block: 'start' });
}
};
mapHTMLElement.addEventListener('wheel', myScrollIntoViewEvent);

// Start checking for layers result sets to be ready
this.#checkLayerResultSetReady().catch((error) => {
// Log
Expand Down
2 changes: 0 additions & 2 deletions packages/geoview-core/src/ui/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ export {
Menu as MenuIcon,
MoreHoriz as MoreHorizIcon,
MoreVert as MoreVertIcon,
MoveDownRounded as MoveDownRoundedIcon,
MoveUpRounded as MoveUpRoundedIcon,
Opacity as OpacityIcon,
OpenInBrowser as OpenInBrowserIcon,
Pause as PauseIcon,
Expand Down
Loading

0 comments on commit 7438da9

Please sign in to comment.