From 4bc8c1374459585f8eb770784f8b1826a184b3e4 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 10 Apr 2019 09:43:19 -0600 Subject: [PATCH] [Maps] expand/collapse Layer TOC (#34506) * [Maps] expand/collapse Layer TOC * Design edits (#30) * fix jest test snapshots * make default isLayerTOCOpen a constant * use newly release EUI menuLeft and menuRight icons instead of arrow icon --- .../maps/public/angular/map_controller.js | 10 +- .../public/angular/services/saved_gis_map.js | 5 +- .../widget_overlay/_widget_overlay.scss | 14 +- .../__snapshots__/view.test.js.snap | 229 +++++++++++------- .../layer_control/_layer_control.scss | 17 ++ .../widget_overlay/layer_control/index.js | 9 + .../widget_overlay/layer_control/view.js | 116 ++++++--- .../widget_overlay/layer_control/view.test.js | 17 +- .../widget_overlay/widget_overlay.js | 2 +- .../maps/public/embeddable/map_embeddable.js | 29 ++- x-pack/plugins/maps/public/store/ui.js | 13 + 11 files changed, 334 insertions(+), 127 deletions(-) diff --git a/x-pack/plugins/maps/public/angular/map_controller.js b/x-pack/plugins/maps/public/angular/map_controller.js index 6ea9e984785c14..c611cd8f0c2714 100644 --- a/x-pack/plugins/maps/public/angular/map_controller.js +++ b/x-pack/plugins/maps/public/angular/map_controller.js @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import _ from 'lodash'; import chrome from 'ui/chrome'; import 'ui/listen'; import React from 'react'; @@ -25,10 +26,12 @@ import { clearTransientLayerStateAndCloseFlyout, } from '../actions/store_actions'; import { + DEFAULT_IS_LAYER_TOC_OPEN, enableFullScreen, getIsFullScreen, updateFlyout, - FLYOUT_STATE + FLYOUT_STATE, + setIsLayerTOCOpen } from '../store/ui'; import { getUniqueIndexPatternIds } from '../selectors/map_selectors'; import { getInspectorAdapters } from '../store/non_serializable_instances'; @@ -138,6 +141,11 @@ app.controller('GisMapController', ($scope, $route, config, kbnUrl, localStorage })); } + if (savedMap.uiStateJSON) { + const uiState = JSON.parse(savedMap.uiStateJSON); + store.dispatch(setIsLayerTOCOpen(_.get(uiState, 'isLayerTOCOpen', DEFAULT_IS_LAYER_TOC_OPEN))); + } + const layerList = getInitialLayers(savedMap.layerListJSON); store.dispatch(replaceLayerList(layerList)); diff --git a/x-pack/plugins/maps/public/angular/services/saved_gis_map.js b/x-pack/plugins/maps/public/angular/services/saved_gis_map.js index 98b725e7997df3..9c2f4426961e96 100644 --- a/x-pack/plugins/maps/public/angular/services/saved_gis_map.js +++ b/x-pack/plugins/maps/public/angular/services/saved_gis_map.js @@ -17,6 +17,7 @@ import { getRefreshConfig, getQuery, } from '../../selectors/map_selectors'; +import { getIsLayerTOCOpen } from '../../store/ui'; import { convertMapExtentToPolygon } from '../../elasticsearch_geo_utils'; import { copyPersistentState } from '../../store/util'; import { extractReferences, injectReferences } from '../../../common/migrations/references'; @@ -99,7 +100,9 @@ module.factory('SavedGisMap', function (Private) { query: _.omit(getQuery(state), 'queryLastTriggeredAt'), }); - this.uiStateJSON = JSON.stringify({}); + this.uiStateJSON = JSON.stringify({ + isLayerTOCOpen: getIsLayerTOCOpen(state) + }); this.bounds = convertMapExtentToPolygon(getMapExtent(state)); }; diff --git a/x-pack/plugins/maps/public/components/widget_overlay/_widget_overlay.scss b/x-pack/plugins/maps/public/components/widget_overlay/_widget_overlay.scss index 9eae0f3ee046f5..433509a0060e0f 100644 --- a/x-pack/plugins/maps/public/components/widget_overlay/_widget_overlay.scss +++ b/x-pack/plugins/maps/public/components/widget_overlay/_widget_overlay.scss @@ -18,8 +18,13 @@ max-width: 24rem; } +.mapWidgetOverlay__layerWrapper { + align-items: flex-end; +} + .mapWidgetControl { max-height: 100%; + width: 100%; overflow: hidden; padding-bottom: $euiSizeS; // ensures the scrollbar doesn't appear unnecessarily because of flex group negative margins border-color: transparent !important; @@ -30,11 +35,12 @@ &.mapWidgetControl-hasShadow { @include euiBottomShadowLarge; } +} - .mapWidgetControl__header { - padding: $euiSizeS $euiSize; - flex-shrink: 0; - } +.mapWidgetControl__header { + padding: 0 $euiSize; + flex-shrink: 0; + text-transform: uppercase; } diff --git a/x-pack/plugins/maps/public/components/widget_overlay/layer_control/__snapshots__/view.test.js.snap b/x-pack/plugins/maps/public/components/widget_overlay/layer_control/__snapshots__/view.test.js.snap index 435cfc123033f3..f46356ae3e0bbb 100644 --- a/x-pack/plugins/maps/public/components/widget_overlay/layer_control/__snapshots__/view.test.js.snap +++ b/x-pack/plugins/maps/public/components/widget_overlay/layer_control/__snapshots__/view.test.js.snap @@ -1,102 +1,163 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`LayerControl is rendered 1`] = ` - - + - - - -

- -

-
-
- - + +

+ +

+
+
+ - - - -
-
- + + + + + + + + +
+ + - - - + + + `; -exports[`LayerControl props isReadOnly 1`] = ` - - + +`; + +exports[`LayerControl props isReadOnly 1`] = ` + + - - - + + +

+ +

+
+
+ -

- + -

-
-
-
-
- - - -
+ + + + + + + + + `; diff --git a/x-pack/plugins/maps/public/components/widget_overlay/layer_control/_layer_control.scss b/x-pack/plugins/maps/public/components/widget_overlay/layer_control/_layer_control.scss index 9f07b295a4e3c4..381d4b24f8e457 100644 --- a/x-pack/plugins/maps/public/components/widget_overlay/layer_control/_layer_control.scss +++ b/x-pack/plugins/maps/public/components/widget_overlay/layer_control/_layer_control.scss @@ -3,3 +3,20 @@ overflow-y: auto; flex-basis: auto !important; // Fixes IE and ensures the layer items are visible } + +.mapLayerControl__addLayerButton, +.mapLayerControl__openLayerTOCButton { + pointer-events: all; + + &:enabled, + &:enabled:hover, + &:enabled:focus { + @include euiBottomShadowLarge; + } +} + +.mapLayerControl__openLayerTOCButton, +.mapLayerControl__closeLayerTOCButton { + @include size($euiSizeXL); + background-color: $euiColorEmptyShade; +} diff --git a/x-pack/plugins/maps/public/components/widget_overlay/layer_control/index.js b/x-pack/plugins/maps/public/components/widget_overlay/layer_control/index.js index efe88a4f35703f..5314b78b467136 100644 --- a/x-pack/plugins/maps/public/components/widget_overlay/layer_control/index.js +++ b/x-pack/plugins/maps/public/components/widget_overlay/layer_control/index.js @@ -8,13 +8,16 @@ import { connect } from 'react-redux'; import { LayerControl } from './view'; import { getIsReadOnly, + getIsLayerTOCOpen, updateFlyout, FLYOUT_STATE, + setIsLayerTOCOpen, } from '../../../store/ui'; function mapStateToProps(state = {}) { return { isReadOnly: getIsReadOnly(state), + isLayerTOCOpen: getIsLayerTOCOpen(state), }; } @@ -23,6 +26,12 @@ function mapDispatchToProps(dispatch) { showAddLayerWizard: () => { dispatch(updateFlyout(FLYOUT_STATE.ADD_LAYER_WIZARD)); }, + closeLayerTOC: () => { + dispatch(setIsLayerTOCOpen(false)); + }, + openLayerTOC: () => { + dispatch(setIsLayerTOCOpen(true)); + }, }; } diff --git a/x-pack/plugins/maps/public/components/widget_overlay/layer_control/view.js b/x-pack/plugins/maps/public/components/widget_overlay/layer_control/view.js index fe5442f1940327..8dd7e1ac29870d 100644 --- a/x-pack/plugins/maps/public/components/widget_overlay/layer_control/view.js +++ b/x-pack/plugins/maps/public/components/widget_overlay/layer_control/view.js @@ -4,25 +4,53 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { Fragment } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiPanel, - EuiButtonEmpty, + EuiButton, EuiTitle, + EuiSpacer, + EuiButtonIcon, + EuiToolTip, } from '@elastic/eui'; import { LayerTOC } from './layer_toc'; import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; + +export function LayerControl({ isReadOnly, isLayerTOCOpen, showAddLayerWizard, closeLayerTOC, openLayerTOC }) { + if (!isLayerTOCOpen) { + return ( + + + + ); + } -export function LayerControl({ isReadOnly, showAddLayerWizard }) { let addLayer; if (!isReadOnly) { addLayer = ( - - + + @@ -30,37 +58,59 @@ export function LayerControl({ isReadOnly, showAddLayerWizard }) { id="xpack.maps.layerControl.addLayerButtonLabel" defaultMessage="Add layer" /> - - + + ); } return ( - - - - - -

- + + + + + +

+ +

+
+
+ + + -

-
-
- {addLayer} -
-
+ + + + + + + + +
+ + {addLayer} - - - - + ); } diff --git a/x-pack/plugins/maps/public/components/widget_overlay/layer_control/view.test.js b/x-pack/plugins/maps/public/components/widget_overlay/layer_control/view.test.js index aba7733dd8ed66..e4369140d8162e 100644 --- a/x-pack/plugins/maps/public/components/widget_overlay/layer_control/view.test.js +++ b/x-pack/plugins/maps/public/components/widget_overlay/layer_control/view.test.js @@ -16,7 +16,10 @@ import { shallowWithIntl } from 'test_utils/enzyme_helpers'; import { LayerControl } from './view'; const defaultProps = { - showAddLayerWizard: () => {} + showAddLayerWizard: () => {}, + closeLayerTOC: () => {}, + openLayerTOC: () => {}, + isLayerTOCOpen: true, }; describe('LayerControl', () => { @@ -43,5 +46,17 @@ describe('LayerControl', () => { expect(component) .toMatchSnapshot(); }); + + test('Should not render LayerTOC when isLayerTOCOpen is false', () => { + const component = shallowWithIntl( + + ); + + expect(component) + .toMatchSnapshot(); + }); }); }); diff --git a/x-pack/plugins/maps/public/components/widget_overlay/widget_overlay.js b/x-pack/plugins/maps/public/components/widget_overlay/widget_overlay.js index 3974737664ac72..ea858ba8997d81 100644 --- a/x-pack/plugins/maps/public/components/widget_overlay/widget_overlay.js +++ b/x-pack/plugins/maps/public/components/widget_overlay/widget_overlay.js @@ -23,7 +23,7 @@ export function WidgetOverlay() { justifyContent="spaceBetween" responsive={false} > - + diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.js b/x-pack/plugins/maps/public/embeddable/map_embeddable.js index 5227b53f052731..02d133bf42dc44 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable.js +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.js @@ -22,7 +22,13 @@ import { setQuery, setRefreshConfig } from '../actions/store_actions'; -import { setReadOnly, setFilterable } from '../store/ui'; +import { + DEFAULT_IS_LAYER_TOC_OPEN, + getIsLayerTOCOpen, + setReadOnly, + setFilterable, + setIsLayerTOCOpen +} from '../store/ui'; import { getInspectorAdapters } from '../store/non_serializable_instances'; import { getMapCenter, getMapZoom } from '../selectors/map_selectors'; @@ -84,6 +90,13 @@ export class MapEmbeddable extends Embeddable { this._store.dispatch(setReadOnly(true)); this._store.dispatch(setFilterable(true)); + if (_.has(this._embeddableConfig, 'isLayerTOCOpen')) { + this._store.dispatch(setIsLayerTOCOpen(this._embeddableConfig.isLayerTOCOpen)); + } else if (this._savedMap.uiStateJSON) { + const uiState = JSON.parse(this._savedMap.uiStateJSON); + this._store.dispatch(setIsLayerTOCOpen(_.get(uiState, 'isLayerTOCOpen', DEFAULT_IS_LAYER_TOC_OPEN))); + } + if (this._embeddableConfig.mapCenter) { this._store.dispatch(setGotoWithCenter({ lat: this._embeddableConfig.mapCenter.lat, @@ -136,18 +149,30 @@ export class MapEmbeddable extends Embeddable { } _handleStoreChanges() { + let embeddableConfigChanged = false; + const center = getMapCenter(this._store.getState()); const zoom = getMapZoom(this._store.getState()); - if (!this._embeddableConfig.mapCenter || this._embeddableConfig.mapCenter.lat !== center.lat || this._embeddableConfig.mapCenter.lon !== center.lon || this._embeddableConfig.mapCenter.zoom !== zoom) { + embeddableConfigChanged = true; this._embeddableConfig.mapCenter = { lat: center.lat, lon: center.lon, zoom: zoom, }; + } + + const isLayerTOCOpen = getIsLayerTOCOpen(this._store.getState()); + if (!this._embeddableConfig.isLayerTOCOpen + || this._embeddableConfig.isLayerTOCOpen !== isLayerTOCOpen) { + embeddableConfigChanged = true; + this._embeddableConfig.isLayerTOCOpen = isLayerTOCOpen; + } + + if (embeddableConfigChanged) { this._onEmbeddableStateChanged({ customization: this._embeddableConfig }); diff --git a/x-pack/plugins/maps/public/store/ui.js b/x-pack/plugins/maps/public/store/ui.js index 6334d49b0a3201..408df7ed673886 100644 --- a/x-pack/plugins/maps/public/store/ui.js +++ b/x-pack/plugins/maps/public/store/ui.js @@ -6,6 +6,7 @@ export const UPDATE_FLYOUT = 'UPDATE_FLYOUT'; export const CLOSE_SET_VIEW = 'CLOSE_SET_VIEW'; export const OPEN_SET_VIEW = 'OPEN_SET_VIEW'; +export const SET_IS_LAYER_TOC_OPEN = 'SET_IS_LAYER_TOC_OPEN'; export const SET_FULL_SCREEN = 'SET_FULL_SCREEN'; export const SET_READ_ONLY = 'SET_READ_ONLY'; export const SET_FILTERABLE = 'IS_FILTERABLE'; @@ -15,10 +16,13 @@ export const FLYOUT_STATE = { ADD_LAYER_WIZARD: 'ADD_LAYER_WIZARD' }; +export const DEFAULT_IS_LAYER_TOC_OPEN = true; + const INITIAL_STATE = { flyoutDisplay: FLYOUT_STATE.NONE, isFullScreen: false, isReadOnly: false, + isLayerTOCOpen: DEFAULT_IS_LAYER_TOC_OPEN, isFilterable: false }; @@ -31,6 +35,8 @@ export function ui(state = INITIAL_STATE, action) { return { ...state, isSetViewOpen: false }; case OPEN_SET_VIEW: return { ...state, isSetViewOpen: true }; + case SET_IS_LAYER_TOC_OPEN: + return { ...state, isLayerTOCOpen: action.isLayerTOCOpen }; case SET_FULL_SCREEN: return { ...state, isFullScreen: action.isFullScreen }; case SET_READ_ONLY: @@ -59,6 +65,12 @@ export function openSetView() { type: OPEN_SET_VIEW, }; } +export function setIsLayerTOCOpen(isLayerTOCOpen) { + return { + type: SET_IS_LAYER_TOC_OPEN, + isLayerTOCOpen + }; +} export function exitFullScreen() { return { type: SET_FULL_SCREEN, @@ -89,6 +101,7 @@ export function setFilterable(isFilterable) { export const getFlyoutDisplay = ({ ui }) => ui && ui.flyoutDisplay || INITIAL_STATE.flyoutDisplay; export const getIsSetViewOpen = ({ ui }) => ui.isSetViewOpen; +export const getIsLayerTOCOpen = ({ ui }) => ui.isLayerTOCOpen; export const getIsFullScreen = ({ ui }) => ui.isFullScreen; export const getIsReadOnly = ({ ui }) => ui.isReadOnly; export const getIsFilterable = ({ ui }) => ui.isFilterable;