From e8ba7a0500ba46f20744040225882822ce9f8ad6 Mon Sep 17 00:00:00 2001 From: Shan He Date: Tue, 31 Aug 2021 00:23:06 -0700 Subject: [PATCH] [Feat] add setMapControlVisibility action to set mapControl visibility (#1590) Signed-off-by: Shan He --- .github/workflows/test.yml | 2 +- src/actions/ui-state-actions.d.ts | 17 ++- src/actions/ui-state-actions.js | 15 +++ src/components/map-container.js | 2 +- src/components/map/locale-panel.js | 6 +- src/constants/action-types.d.ts | 1 + src/constants/action-types.js | 1 + src/constants/default-settings.js | 9 ++ src/constants/index.js | 3 +- src/reducers/ui-state-updaters.d.ts | 4 + src/reducers/ui-state-updaters.js | 39 +++++-- src/reducers/ui-state.js | 1 + .../components/map/map-control-test.js | 101 +++++++++++++----- test/node/reducers/ui-state-test.js | 31 ++++++ 14 files changed, 187 insertions(+), 45 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 431a44dc70..8749d73896 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,6 +42,6 @@ jobs: run: xvfb-run --auto-servernum yarn cover - name: Coveralls - uses: coverallsapp/github-action@v1.1.2 + uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/src/actions/ui-state-actions.d.ts b/src/actions/ui-state-actions.d.ts index dec2af8e73..4530d15d4c 100644 --- a/src/actions/ui-state-actions.d.ts +++ b/src/actions/ui-state-actions.d.ts @@ -57,10 +57,23 @@ export type ToggleMapControlUpdaterAction = { }; }; export function toggleMapControl( - panelId, - index + panelId: string, + index: number ): Merge; + +/** SET_MAP_CONTROL_VISIBILITY */ +export type setMapControlVisibilityUpdaterAction = { + payload: { + panelId: string; + show: boolean; + }; +}; +export function setMapControlVisibility( + panelId: string, + show: boolean +): Merge; + /** OPEN_DELETE_MODAL */ export type OpenDeleteModalUpdaterAction = { payload: string; diff --git a/src/actions/ui-state-actions.js b/src/actions/ui-state-actions.js index c813e41860..3dedab30e2 100644 --- a/src/actions/ui-state-actions.js +++ b/src/actions/ui-state-actions.js @@ -74,6 +74,21 @@ export const toggleMapControl = createAction(ActionTypes.TOGGLE_MAP_CONTROL, (pa index })); +/** + * Toggle active map control panel + * @memberof uiStateActions + * @param panelId - map control panel id, one of the keys of: [`DEFAULT_MAP_CONTROLS`](#default_map_controls) + * @type {typeof import('./ui-state-actions').setMapControlVisibility} + * @public + */ +export const setMapControlVisibility = createAction( + ActionTypes.SET_MAP_CONTROL_VISIBILITY, + (panelId, show) => ({ + panelId, + show + }) +); + /** * Toggle active map control panel * @memberof uiStateActions diff --git a/src/components/map-container.js b/src/components/map-container.js index 67d127772f..2e9718ea13 100644 --- a/src/components/map-container.js +++ b/src/components/map-container.js @@ -535,7 +535,7 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor, MapL const isEdit = (mapControls.mapDraw || {}).active; const hasGeocoderLayer = layers.find(l => l.id === GEOCODER_LAYER_ID); - const isSplit = Boolean(index); + const isSplit = Boolean(mapState.isSplit); return ( <> diff --git a/src/components/map/locale-panel.js b/src/components/map/locale-panel.js index 3729f7a3b1..3192a51bc8 100644 --- a/src/components/map/locale-panel.js +++ b/src/components/map/locale-panel.js @@ -57,7 +57,7 @@ function LocalePanelFactory(MapControlTooltip, MapControlPanel, MapControlToolba return null; } return ( -
+ <> {isActive ? ( {availableLocales.map(locale => ( @@ -77,10 +77,10 @@ function LocalePanelFactory(MapControlTooltip, MapControlPanel, MapControlToolba data-for="locale" disableClose={disableClose} > - {currentLocal.toUpperCase()} + {currentLocal.toUpperCase()} -
+ ); } ); diff --git a/src/constants/action-types.d.ts b/src/constants/action-types.d.ts index 6052500fa5..9bcaf68e9f 100644 --- a/src/constants/action-types.d.ts +++ b/src/constants/action-types.d.ts @@ -87,6 +87,7 @@ export type ActionType = { HIDE_EXPORT_DROPDOWN: string; OPEN_DELETE_MODAL: string; TOGGLE_MAP_CONTROL: string; + SET_MAP_CONTROL_VISIBILITY: string; ADD_NOTIFICATION: string; REMOVE_NOTIFICATION: string; SET_LOCALE: string; diff --git a/src/constants/action-types.js b/src/constants/action-types.js index 3f0f5aabc8..35cb394e4b 100644 --- a/src/constants/action-types.js +++ b/src/constants/action-types.js @@ -138,6 +138,7 @@ const ActionTypes = { HIDE_EXPORT_DROPDOWN: `${ACTION_PREFIX}HIDE_EXPORT_DROPDOWN`, OPEN_DELETE_MODAL: `${ACTION_PREFIX}OPEN_DELETE_MODAL`, TOGGLE_MAP_CONTROL: `${ACTION_PREFIX}TOGGLE_MAP_CONTROL`, + SET_MAP_CONTROL_VISIBILITY: `${ACTION_PREFIX}SET_MAP_CONTROL_VISIBILITY`, ADD_NOTIFICATION: `${ACTION_PREFIX}ADD_NOTIFICATION`, REMOVE_NOTIFICATION: `${ACTION_PREFIX}REMOVE_NOTIFICATION`, SET_LOCALE: `${ACTION_PREFIX}SET_LOCALE`, diff --git a/src/constants/default-settings.js b/src/constants/default-settings.js index 5236eb2ac0..b73a3aee78 100644 --- a/src/constants/default-settings.js +++ b/src/constants/default-settings.js @@ -884,3 +884,12 @@ export const DATASET_FORMATS = keyMirror({ csv: null, keplergl: null }); + +export const MAP_CONTROLS = keyMirror({ + visibleLayers: null, + mapLegend: null, + toggle3d: null, + splitMap: null, + mapDraw: null, + mapLocale: null +}); diff --git a/src/constants/index.js b/src/constants/index.js index 3c435c3377..ea84a6b16c 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -64,7 +64,8 @@ export { DEFAULT_TIME_FORMAT, SPEED_CONTROL_RANGE, RESOLUTIONS, - SORT_ORDER + SORT_ORDER, + MAP_CONTROLS } from './default-settings'; export {BUG_REPORT_LINK, USER_GUIDE_DOC} from './user-guides'; diff --git a/src/reducers/ui-state-updaters.d.ts b/src/reducers/ui-state-updaters.d.ts index 2a407daf36..f604d754f5 100644 --- a/src/reducers/ui-state-updaters.d.ts +++ b/src/reducers/ui-state-updaters.d.ts @@ -115,6 +115,10 @@ export function toggleMapControlUpdater( state: UiState, action: UiStateActions.ToggleMapControlUpdaterAction ): UiState; +export function setMapControlVisibilityUpdater( + state: UiState, + action: UiStateActions.setMapControlVisibilityUpdaterAction +): UiState; export function openDeleteModalUpdater( state: UiState, action: UiStateActions.OpenDeleteModalUpdaterAction diff --git a/src/reducers/ui-state-updaters.js b/src/reducers/ui-state-updaters.js index 6edb2c2b45..be34a69797 100644 --- a/src/reducers/ui-state-updaters.js +++ b/src/reducers/ui-state-updaters.js @@ -28,7 +28,8 @@ import { EXPORT_HTML_MAP_MODES, EXPORT_IMG_RATIOS, EXPORT_MAP_FORMATS, - RESOLUTIONS + RESOLUTIONS, + MAP_CONTROLS } from 'constants/default-settings'; import {LOCALE_CODES} from 'localization/locales'; import {createNotification, errorNotification} from 'utils/notifications-utils'; @@ -99,14 +100,7 @@ const DEFAULT_MAP_CONTROLS_FEATURES = { * @type {import('./ui-state-updaters').MapControls} * @public */ -export const DEFAULT_MAP_CONTROLS = [ - 'visibleLayers', - 'mapLegend', - 'toggle3d', - 'splitMap', - 'mapDraw', - 'mapLocale' -].reduce( +export const DEFAULT_MAP_CONTROLS = Object.keys(MAP_CONTROLS).reduce( (final, current) => ({ ...final, [current]: DEFAULT_MAP_CONTROLS_FEATURES @@ -359,6 +353,33 @@ export const toggleMapControlUpdater = (state, {payload: {panelId, index = 0}}) } }); +/** + * Toggle map control visibility + * @memberof uiStateUpdaters + * @param state `uiState` + * @param action action + * @param action.payload map control panel id, one of the keys of: [`DEFAULT_MAP_CONTROLS`](#default_map_controls) + * @returns nextState + * @type {typeof import('./ui-state-updaters').setMapControlVisibilityUpdater} + * @public + */ +export const setMapControlVisibilityUpdater = (state, {payload: {panelId, show}}) => { + if (!state.mapControls?.[panelId]) { + return state; + } + + return { + ...state, + mapControls: { + ...state.mapControls, + [panelId]: { + ...state.mapControls[panelId], + show: Boolean(show) + } + } + }; +}; + /** * Toggle active map control panel * @memberof uiStateUpdaters diff --git a/src/reducers/ui-state.js b/src/reducers/ui-state.js index 315d58c831..d9fd68d40d 100644 --- a/src/reducers/ui-state.js +++ b/src/reducers/ui-state.js @@ -34,6 +34,7 @@ const actionHandler = { [ActionTypes.HIDE_EXPORT_DROPDOWN]: uiStateUpdaters.hideExportDropdownUpdater, [ActionTypes.OPEN_DELETE_MODAL]: uiStateUpdaters.openDeleteModalUpdater, [ActionTypes.TOGGLE_MAP_CONTROL]: uiStateUpdaters.toggleMapControlUpdater, + [ActionTypes.SET_MAP_CONTROL_VISIBILITY]: uiStateUpdaters.setMapControlVisibilityUpdater, [ActionTypes.ADD_NOTIFICATION]: uiStateUpdaters.addNotificationUpdater, [ActionTypes.REMOVE_NOTIFICATION]: uiStateUpdaters.removeNotificationUpdater, diff --git a/test/browser/components/map/map-control-test.js b/test/browser/components/map/map-control-test.js index c0d800ed32..75e3787fc3 100644 --- a/test/browser/components/map/map-control-test.js +++ b/test/browser/components/map/map-control-test.js @@ -19,15 +19,20 @@ // THE SOFTWARE. import React from 'react'; -import {shallow} from 'enzyme'; import sinon from 'sinon'; import test from 'tape'; +import {IntlWrapper, mountWithTheme} from 'test/helpers/component-utils'; + import MapControlFactory from 'components/map/map-control'; +import {MapControlButton} from 'components/common/styled-components'; + +import {Cube3d, Split, Legend, DrawPolygon, Layers, Delete} from 'components/common/icons'; + import {appInjector} from 'components'; const MapControl = appInjector.get(MapControlFactory); -test('MapControlFactory - display all options', t => { +test('MapControlFactory - display options', t => { const onToggleSplitMap = sinon.spy(); const onTogglePerspective = sinon.spy(); const onToggleMapControl = sinon.spy(); @@ -35,32 +40,72 @@ test('MapControlFactory - display all options', t => { const onToggleEditorVisibility = sinon.spy(); const onSetLocale = sinon.spy(); - const $ = shallow( - - ); - - t.equal($.find('.map-control-action').length, 6, 'Should show 6 action panels'); + const defaultProps = { + mapControls: { + splitMap: {show: true}, + visibleLayers: {show: true}, + toggle3d: {show: true}, + mapLegend: {show: true}, + mapDraw: {show: true}, + mapLocale: {show: true} + }, + datasets: {}, + layers: [], + locale: 'en', + layersToRender: {}, + dragRotate: true, + mapIndex: 0, + onToggleSplitMap, + onTogglePerspective, + onToggleMapControl, + onSetEditorMode, + onToggleEditorVisibility, + onSetLocale + }; + + let wrapper; + t.doesNotThrow(() => { + wrapper = mountWithTheme( + + {' '} + + ); + }, 'BottomWidget should not fail without props'); + + // layer selector is not active + t.equal(wrapper.find(MapControlButton).length, 5, 'Should show 5 MapControlButton'); + + t.equal(wrapper.find(Split).length, 1, 'Should show 1 split map button'); + t.equal(wrapper.find(Cube3d).length, 1, 'Should show 1 toggle 3d button'); + t.equal(wrapper.find(Legend).length, 1, 'Should show 1 map legend button'); + t.equal(wrapper.find(DrawPolygon).length, 1, 'Should show 1 map draw button'); + t.equal(wrapper.find('.map-control-button__locale').length, 1, 'Should show 1 locale button'); + + // with split map and active layer selector + const nextProps = { + ...defaultProps, + isSplit: true, + mapControls: { + ...defaultProps.mapControls, + visibleLayers: {show: true, active: false} + } + }; + + wrapper.setProps({ + children: + }); + + t.equal(wrapper.find(MapControlButton).length, 6, 'Should show 6 MapControlButton'); + t.equal(wrapper.find(Split).length, 0, 'Should show 0 split map split button'); + t.equal(wrapper.find(Delete).length, 1, 'Should show 1 split map delete button'); + t.equal(wrapper.find(Layers).length, 1, 'Should show 1 Layer button'); + + // with 0 mapcontrols + wrapper.setProps({ + children: + }); + + t.equal(wrapper.find(MapControlButton).length, 0, 'Should show 0 MapControlButton'); t.end(); }); diff --git a/test/node/reducers/ui-state-test.js b/test/node/reducers/ui-state-test.js index f5234bdb6e..c042bbf765 100644 --- a/test/node/reducers/ui-state-test.js +++ b/test/node/reducers/ui-state-test.js @@ -26,6 +26,7 @@ import { openDeleteModal, setExportImageSetting, toggleMapControl, + setMapControlVisibility, setExportSelectedDataset, setExportDataType, setExportFiltered, @@ -181,6 +182,36 @@ test('#uiStateReducer -> TOGGLE_MAP_CONTROL', t => { t.end(); }); +test('#uiStateReducer -> SET_MAP_CONTROL_VISIBILITY', t => { + const newReducer = reducer(INITIAL_UI_STATE, setMapControlVisibility('mapLegend', false)); + + const expectedMapControl = { + ...INITIAL_UI_STATE.mapControls, + mapLegend: { + ...INITIAL_UI_STATE.mapControls.mapLegend, + show: false + } + }; + + t.deepEqual(newReducer.mapControls, expectedMapControl, 'should set map legend show to be false'); + + const newReducer1 = reducer(newReducer, setMapControlVisibility('mapLegend', true)); + + const expectedMapControl1 = { + ...INITIAL_UI_STATE.mapControls, + mapLegend: { + ...INITIAL_UI_STATE.mapControls.mapLegend, + show: true + } + }; + + t.deepEqual(newReducer1.mapControls, expectedMapControl1, 'should set map legend show to true'); + + const newReducer2 = reducer(newReducer1, setMapControlVisibility('something', true)); + t.equal(newReducer1, newReducer2, 'should note update state'); + t.end(); +}); + test('#uiStateReducer -> SET_EXPORT_SELECTED_DATASET', t => { const newReducer = reducer(INITIAL_UI_STATE, setExportSelectedDataset('a'));