Skip to content

Commit

Permalink
[Chore] Refactored map control and decoupled action components (#1552)
Browse files Browse the repository at this point in the history
* chore: Refactored map control and decoupled action components

Signed-off-by: Giuseppe Macri <[email protected]>
  • Loading branch information
heshan0131 authored Aug 29, 2021
1 parent 2f8b19f commit d8db8f6
Show file tree
Hide file tree
Showing 29 changed files with 931 additions and 730 deletions.
2 changes: 1 addition & 1 deletion examples/demo-app/src/factories/map-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function CustomMapControlFactory(...deps) {
const StyledMapControlOverlay = styled.div`
position: absolute;
top: ${props => props.top}px;
right: 0px;
right: 0;
z-index: 1;
`;

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -283,4 +283,4 @@
"volta": {
"node": "12.19.0"
}
}
}
16 changes: 10 additions & 6 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,15 @@ export {default as MapPopoverFactory} from './map/map-popover';
export {default as MapControlFactory} from './map/map-control';
export {default as LayerHoverInfoFactory} from './map/layer-hover-info';
export {default as CoordinateInfoFactory} from './map/coordinate-info';
export {
Toggle3dButtonFactory,
MapDrawPanelFactory,
SplitMapButtonFactory,
MapLegendPanelFactory
} from './map/map-control';
export {default as LayerSelectorPanelFactory} from './map/layer-selector-panel';
export {default as LocalePanelFactory} from './map/locale-panel';
export {default as MapControlPanelFactory} from './map/map-control-panel';
export {default as MapControlTooltipFactory} from './map/map-control-tooltip';
export {default as MapLegendFactory} from './map/map-legend';
export {default as MapDrawPanelFactory} from './map/map-draw-panel';
export {default as SplitMapButtonFactory} from './map/split-map-button';
export {default as MapLegendPanelFactory} from './map/map-legend-panel';
export {default as Toggle3dButtonFactory} from './map/toggle-3d-button';

// // modal factories
export {default as ModalDialogFactory} from './modals/modal-dialog';
Expand Down Expand Up @@ -187,6 +190,7 @@ export {default as MapLegend} from 'components/map/map-legend';

export * from './common/styled-components';
import * as Icons from './common/icons';

export {Icons};

// Individual Component from Dependency Tree
Expand Down
15 changes: 15 additions & 0 deletions src/components/map/layer-selector-panel.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import {Layer} from 'layers';
import {MapControls} from 'reducers/ui-state-updaters';

export type LayerSelectorPanelProps = {
onMapToggleLayer: (layerId: string) => void;
onToggleMapControl: (control: string) => void;
layers: ReadonlyArray<Layer>;
layersToRender: {[key: string]: boolean};
isSplit: boolean;
mapControls: MapControls;
readOnly: boolean;
};

export type LayerSelectorPanelComponent = React.FunctionComponent<LayerSelectorPanelProps>;
83 changes: 83 additions & 0 deletions src/components/map/layer-selector-panel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React, {useCallback, useMemo} from 'react';
import {MapControlButton} from 'components/common/styled-components';
import {Layers} from '../common/icons';
import MapLayerSelector from '../common/map-layer-selector';
import MapControlTooltipFactory from './map-control-tooltip';
import MapControlPanelFactory from './map-control-panel';

LayerSelectorPanelFactory.deps = [MapControlTooltipFactory, MapControlPanelFactory];

function LayerSelectorPanelFactory(MapControlTooltip, MapControlPanel) {
/** @type {import('./layer-selector-panel').LayerSelectorPanelComponent} */
const LayerSelectorPanel = ({
onMapToggleLayer,
onToggleMapControl,
layers,
layersToRender,
isSplit,
mapControls,
readOnly
}) => {
const visibleLayers = mapControls?.visibleLayers || {};
const {active: isActive, show, disableClose} = visibleLayers;

const legendLayers = useMemo(
() =>
layers
.filter(({config}) => config.isVisible)
.map(({id, config}) => ({
id,
name: config.label,
// layer
isVisible: layersToRender[id]
})),
[layers, layersToRender]
);

const isVisible = useMemo(() => isSplit && show && readOnly !== true, [
isSplit,
show,
readOnly
]);

const onToggleMenuPanel = useCallback(
event => {
event.preventDefault();
onToggleMapControl('visibleLayers');
},
[onToggleMapControl]
);

return isVisible ? (
(!isActive ? (
<MapControlButton
key={1}
onClick={onToggleMenuPanel}
className="map-control-button toggle-layer"
data-tip
data-for="toggle-layer"
>
<Layers height="22px" />
<MapControlTooltip
id="toggle-layer"
message={isActive ? 'tooltip.hideLayerPanel' : 'tooltip.showLayerPanel'}
/>
</MapControlButton>
) : (
<MapControlPanel
header="header.visibleLayers"
onClick={onToggleMenuPanel}
disableClose={disableClose}
>
<MapLayerSelector layers={legendLayers} onMapToggleLayer={onMapToggleLayer} />
</MapControlPanel>
))
) : null;
};

LayerSelectorPanel.displayName = 'LayerSelectorPanel';

return React.memo(LayerSelectorPanel);
}

export default LayerSelectorPanelFactory;
12 changes: 12 additions & 0 deletions src/components/map/locale-panel.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import {MapControls} from '../../reducers';

export type LocalePanelProps = {
availableLocales: ReadnlyArray<string>;
onSetLocale: (locale: string) => void;
locale: string;
onToggleMenuPanel: () => void;
mapControls: MapControls;
};

export type LocalePanelComponent = React.FunctionComponent<LocalePanelProps>;
73 changes: 73 additions & 0 deletions src/components/map/locale-panel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React, {useCallback} from 'react';
import ToolbarItem from 'components/common/toolbar-item';
import {MapControlButton} from 'components/common/styled-components';
import MapControlTooltipFactory from './map-control-tooltip';
import MapControlPanelFactory from './map-control-panel';
import MapControlToolbarFactory from './map-control-toolbar';

LocalePanelFactory.deps = [
MapControlTooltipFactory,
MapControlPanelFactory,
MapControlToolbarFactory
];

function LocalePanelFactory(MapControlTooltip, MapControlPanel, MapControlToolbar) {
/** @type {import('./locale-panel').LocalePanelComponent} */
const LocalePanel = React.memo(
({availableLocales, onToggleMenuPanel, onSetLocale, locale: currentLocal, mapControls}) => {
const {active: isActive, disableClose} = mapControls.mapLocale || {};

const onClickItem = useCallback(
locale => {
onSetLocale(locale);
},
[onSetLocale]
);

const onClickButton = useCallback(
e => {
e.preventDefault();
onToggleMenuPanel();
},
[onToggleMenuPanel]
);
const getLabel = useCallback(locale => `toolbar.${locale}`, []);

if (!mapControls.mapLocale) {
return null;
}
return (
<div style={{position: 'relative'}}>
{isActive ? (
<MapControlToolbar show={isActive}>
{availableLocales.map(locale => (
<ToolbarItem
key={locale}
onClick={() => onClickItem(locale)}
label={getLabel(locale)}
active={currentLocal === locale}
/>
))}
</MapControlToolbar>
) : null}
<MapControlButton
onClick={onClickButton}
active={isActive}
data-tip
data-for="locale"
disableClose={disableClose}
>
{currentLocal.toUpperCase()}
<MapControlTooltip id="locale" message="tooltip.selectLocale" />
</MapControlButton>
</div>
);
}
);

LocalePanel.displayName = 'LocalePanel';

return LocalePanel;
}

export default LocalePanelFactory;
11 changes: 11 additions & 0 deletions src/components/map/map-control-panel.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';

export type MapControlPanelProps = {
header?: string;
scale?: number;
onClick: () => void;
isExport?: boolean;
logoComponent?: Element;
};

export type MapControlPanelComponent = React.FunctionComponent<MapControlPanelProps>;
78 changes: 78 additions & 0 deletions src/components/map/map-control-panel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React from 'react';
import styled from 'styled-components';
import {FormattedMessage} from 'localization';
import {IconRoundSmall} from 'components/common/styled-components';
import {Close} from 'components/common/icons';

const StyledMapControlPanel = styled.div`
background-color: ${props => props.theme.mapPanelBackgroundColor};
flex-grow: 1;
z-index: 1;
p {
margin-bottom: 0;
}
`;

const StyledMapControlPanelContent = styled.div.attrs({
className: 'map-control__panel-content'
})`
${props => props.theme.dropdownScrollBar};
max-height: 500px;
min-height: 100px;
min-width: ${props => props.theme.mapControl.width}px;
overflow: auto;
`;

const StyledMapControlPanelHeader = styled.div.attrs({
className: 'map-control__panel-header'
})`
display: flex;
justify-content: space-between;
background-color: ${props => props.theme.mapPanelHeaderBackgroundColor};
height: 32px;
padding: 6px 12px;
font-size: 11px;
color: ${props => props.theme.titleTextColor};
position: relative;
button {
width: 18px;
height: 18px;
}
`;

function MapControlPanelFactory() {
/** @type {import('./map-control-panel').MapControlPanelComponent} */
const MapControlPanel = React.memo(
({children, header, onClick, scale = 1, isExport, logoComponent}) => (
<StyledMapControlPanel
style={{
transform: `scale(${scale})`,
marginBottom: '8px'
}}
>
<StyledMapControlPanelHeader>
{isExport && logoComponent ? (
logoComponent
) : header ? (
<span style={{verticalAlign: 'middle'}}>
<FormattedMessage id={header} />
</span>
) : null}
{isExport ? null : (
<IconRoundSmall className="close-map-control-item" onClick={onClick}>
<Close height="16px" />
</IconRoundSmall>
)}
</StyledMapControlPanelHeader>
<StyledMapControlPanelContent>{children}</StyledMapControlPanelContent>
</StyledMapControlPanel>
)
);

MapControlPanel.displayName = 'MapControlPanel';

return MapControlPanel;
}

export default MapControlPanelFactory;
13 changes: 13 additions & 0 deletions src/components/map/map-control-toolbar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import styled from 'styled-components';
import VerticalToolbar from '../common/vertical-toolbar';

function MapControlToolbar() {
const StyledToolbar = styled(VerticalToolbar)`
position: absolute;
right: 32px;
`;

return StyledToolbar;
}

export default MapControlToolbar;
8 changes: 8 additions & 0 deletions src/components/map/map-control-tooltip.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react';

export type MapControlTooltipProps = {
id: string;
message: string;
};

export type MapControlTooltipComponent = React.FunctionComponent<MapControlTooltipProps>;
20 changes: 20 additions & 0 deletions src/components/map/map-control-tooltip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import {Tooltip} from '..';
import {FormattedMessage} from 'localization';

function MapControlTooltipFactory() {
/** @type {import('./map-control-tooltip').MapControlTooltipComponent} */
const MapControlTooltip = React.memo(({id, message}) => (
<Tooltip id={id} place="left" effect="solid">
<span>
<FormattedMessage id={message} />
</span>
</Tooltip>
));

MapControlTooltip.displayName = 'MapControlTooltip';

return MapControlTooltip;
}

export default MapControlTooltipFactory;
Loading

0 comments on commit d8db8f6

Please sign in to comment.