Skip to content

Commit

Permalink
Fix geosolutions-it#2803 add popover overlay to the sync tool in feat…
Browse files Browse the repository at this point in the history
…ure grid
  • Loading branch information
MV88 committed Apr 18, 2018
1 parent 4b1e103 commit 17412f6
Show file tree
Hide file tree
Showing 26 changed files with 275 additions and 44 deletions.
14 changes: 13 additions & 1 deletion web/client/actions/__tests__/featuregrid-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ const {
START_SYNC_WMS, startSyncWMS,
storeAdvancedSearchFilter, STORE_ADVANCED_SEARCH_FILTER,
fatureGridQueryResult, GRID_QUERY_RESULT,
moreFeatures, LOAD_MORE_FEATURES
moreFeatures, LOAD_MORE_FEATURES,
hideSyncPopover, HIDE_SYNC_POPOVER,
toggleShowAgain, TOGGLE_SHOW_AGAIN_FLAG
} = require('../featuregrid');

const idFeature = "2135";
Expand Down Expand Up @@ -96,6 +98,16 @@ describe('Test correctness of featurgrid actions', () => {
expect(retval).toExist();
expect(retval.type).toBe(CLEAR_CHANGES_CONFIRMED);
});
it('Test hideSyncPopover action creator', () => {
const retval = hideSyncPopover();
expect(retval).toExist();
expect(retval.type).toBe(HIDE_SYNC_POPOVER);
});
it('Test toggleShowAgain action creator', () => {
const retval = toggleShowAgain();
expect(retval).toExist();
expect(retval.type).toBe(TOGGLE_SHOW_AGAIN_FLAG);
});
it('Test startDrawingFeature action creator', () => {
const retval = startDrawingFeature();
expect(retval).toExist();
Expand Down
14 changes: 14 additions & 0 deletions web/client/actions/featuregrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ const OPEN_ADVANCED_SEARCH = 'FEATUREGRID:ADVANCED_SEARCH';
const ZOOM_ALL = 'FEATUREGRID:ZOOM_ALL';
const INIT_PLUGIN = 'FEATUREGRID:INIT_PLUGIN';
const SIZE_CHANGE = 'FEATUREGRID:SIZE_CHANGE';
const TOGGLE_SHOW_AGAIN_FLAG = 'FEATUREGRID:TOGGLE_SHOW_AGAIN_FLAG';
const HIDE_SYNC_POPOVER = 'FEATUREGRID:HIDE_SYNC_POPOVER';

const MODES = {
EDIT: "EDIT",
Expand All @@ -56,6 +58,16 @@ const STORE_ADVANCED_SEARCH_FILTER = 'STORE_ADVANCED_SEARCH_FILTER';
const LOAD_MORE_FEATURES = "LOAD_MORE_FEATURES";
const GRID_QUERY_RESULT = 'FEATUREGRID:QUERY_RESULT';

function toggleShowAgain() {
return {
type: TOGGLE_SHOW_AGAIN_FLAG
};
}
function hideSyncPopover() {
return {
type: HIDE_SYNC_POPOVER
};
}
function fatureGridQueryResult(features, pages) {
return {
type: GRID_QUERY_RESULT,
Expand Down Expand Up @@ -381,6 +393,8 @@ module.exports = {
toggleEditMode,
toggleViewMode,
initPlugin, INIT_PLUGIN,
hideSyncPopover, HIDE_SYNC_POPOVER,
toggleShowAgain, TOGGLE_SHOW_AGAIN_FLAG,
START_SYNC_WMS, startSyncWMS,
STOP_SYNC_WMS,
storeAdvancedSearchFilter, STORE_ADVANCED_SEARCH_FILTER,
Expand Down
11 changes: 11 additions & 0 deletions web/client/components/data/featuregrid/enhancers/withHint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

const {compose, branch} = require('recompose');
const tooltip = require('../../../misc/enhancers/tooltip');
const withPopover = require('./withPopover');
module.exports = compose(
branch(
(({renderPopover} = {}) => renderPopover),
withPopover,
tooltip
)
);
28 changes: 28 additions & 0 deletions web/client/components/data/featuregrid/enhancers/withPopover.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const React = require('react');
const Overlay = require('../../../misc/Overlay');
const {Popover} = require('react-bootstrap');
const ReactDOM = require('react-dom');

/**
* An overlay popover is added to a Wrapped component
* @param {object} Wrapped must be a class component, do not use a functional
* component because it misses the refs property
* you can customize popover props, content and placement
*/
module.exports = (Wrapped) => class WithPopover extends React.Component {
render() {
let target = null;
const {popoverOptions, ...props} = this.props;
return (
<span className="mapstore-info-popover">
<Wrapped {...this.props} ref={button => { target = button; }} />
<Overlay placement={popoverOptions.placement} show target={() => ReactDOM.findDOMNode(target)}>
<Popover
{...popoverOptions.props}>
{popoverOptions.content}
</Popover>
</Overlay>
</span>
);
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const React = require('react');
const OverlayTrigger = require('../../../misc/OverlayTrigger');
const {Tooltip} = require('react-bootstrap');

module.exports = (Wrapped) => ({tooltip, id, placement, ...props}) =>
(<OverlayTrigger placement={placement} overlay={<Tooltip id={`fe-${id}`}>{tooltip}</Tooltip>}>
<Wrapped {...props}/>
</OverlayTrigger>);
20 changes: 10 additions & 10 deletions web/client/components/data/featuregrid/toolbars/TButton.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
const React = require('react');
const {Button, Glyphicon, Tooltip} = require('react-bootstrap');
const OverlayTrigger = require('../../../misc/OverlayTrigger');
const {Button, Glyphicon} = require('react-bootstrap');
const hideStyle = {
width: 0,
padding: 0,
borderWidth: 0
};
const normalStyle = {
};

const normalStyle = {};
const getStyle = (visible) => visible ? normalStyle : hideStyle;
module.exports = ({disabled, id, tooltip="", visible, onClick, glyph, active, className = "square-button"}) =>
(<OverlayTrigger placement="top" overlay={<Tooltip id={`fe-${id}`}>{tooltip}</Tooltip>}>
<Button key={id} bsStyle={active ? "success" : "primary"} disabled={disabled} id={`fg-${id}`}

module.exports = class SimpleTButton extends React.Component {
render() {
const {disabled, id, visible, onClick, glyph, active, className = "square-button", ...props} = this.props;
return (<Button {...props} bsStyle={active ? "success" : "primary"} disabled={disabled} id={`fg-${id}`}
style={getStyle(visible)}
className={className}
onClick={() => !disabled && onClick()}>
<Glyphicon glyph={glyph}/>
</Button>
</OverlayTrigger>);
</Button>);
}
};
99 changes: 71 additions & 28 deletions web/client/components/data/featuregrid/toolbars/Toolbar.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
const React = require('react');
const {ButtonGroup} = require('react-bootstrap');
const {ButtonGroup, Glyphicon, Checkbox} = require('react-bootstrap');
require("./toolbar.css");
const Message = require('../../../I18N/Message');
const TButton = require("./TButton");
const withHint = require("../enhancers/withHint");
const TButton = withHint(require("./TButton"));
const getDrawFeatureTooltip = (isDrawing, isSimpleGeom) => {
if (isDrawing) {
return "featuregrid.toolbar.stopDrawGeom";
Expand All @@ -15,111 +16,153 @@ const getSaveMessageId = ({saving, saved}) => {
}
return "featuregrid.toolbar.saveChanges";
};

module.exports = ({events = {}, mode = "VIEW", showChartButton = true, selectedCount, hasChanges, hasGeometry, hasNewFeatures, isSimpleGeom, isDrawing = false, isEditingAllowed, saving = false, saved = false, isDownloadOpen, isColumnsOpen, disableToolbar, isSearchAllowed, disableDownload, displayDownload, isSyncActive = false, hasSupportedGeometry = true, disableZoomAll = false} = {}) =>

(<ButtonGroup id="featuregrid-toolbar" className="featuregrid-toolbar featuregrid-toolbar-margin">
module.exports = ({events = {}, syncPopover = {showPopoverSync: true, dockSize: "32.2%"}, mode = "VIEW", showChartButton = true, selectedCount, hasChanges, hasGeometry, hasNewFeatures, isSimpleGeom, isDrawing = false, isEditingAllowed, saving = false, saved = false, isDownloadOpen, isColumnsOpen, disableToolbar, isSearchAllowed, disableDownload, displayDownload, isSyncActive = false, hasSupportedGeometry = true, disableZoomAll = false} = {}) => {
return (<ButtonGroup id="featuregrid-toolbar" className="featuregrid-toolbar featuregrid-toolbar-margin">
<TButton
id="edit-mode"
tooltip={<Message msgId="featuregrid.toolbar.editMode"/>}
key="edit-mode"
tooltipId="featuregrid.toolbar.editMode"
disabled={disableToolbar}
visible={mode === "VIEW" && isEditingAllowed}
onClick={events.switchEditMode}
glyph="pencil"/>
<TButton
id="search"
tooltip={<Message msgId="featuregrid.toolbar.advancedFilter"/>}
key="search"
tooltipId="featuregrid.toolbar.advancedFilter"
disabled={disableToolbar || !isSearchAllowed}
visible={mode === "VIEW"}
onClick={events.showQueryPanel}
glyph="filter"/>
<TButton
id="zoom-all"
tooltip={<Message msgId="featuregrid.toolbar.zoomAll"/>}
key="zoom-all"
tooltipId="featuregrid.toolbar.zoomAll"
disabled={disableToolbar || disableZoomAll}
visible={mode === "VIEW"}
onClick={events.zoomAll}
glyph="zoom-to"/>
<TButton
id="back-view"
tooltip={<Message msgId="featuregrid.toolbar.quitEditMode"/>}
key="back-view"
tooltipId="featuregrid.toolbar.quitEditMode"
disabled={disableToolbar}
visible={mode === "EDIT" && !hasChanges && !hasNewFeatures}
onClick={events.switchViewMode}
glyph="arrow-left"/>
<TButton
id="add-feature"
tooltip={<Message msgId="featuregrid.toolbar.addNewFeatures"/>}
key="add-feature"
tooltipId="featuregrid.toolbar.addNewFeatures"
disabled={disableToolbar}
visible={mode === "EDIT" && !hasNewFeatures && !hasChanges && hasSupportedGeometry}
onClick={events.createFeature}
glyph="row-add"/>
<TButton
id="draw-feature"
tooltip={<Message msgId={getDrawFeatureTooltip(isDrawing, isSimpleGeom)}/>}
key="draw-feature"
tooltipId={getDrawFeatureTooltip(isDrawing, isSimpleGeom)}
disabled={disableToolbar}
visible={mode === "EDIT" && selectedCount === 1 && (!hasGeometry || hasGeometry && !isSimpleGeom) && hasSupportedGeometry}
onClick={events.startDrawingFeature}
active={isDrawing}
glyph="pencil-add"/>
<TButton
id="remove-features"
tooltip={<Message msgId="featuregrid.toolbar.deleteSelectedFeatures"/>}
key="remove-features"
tooltipId="featuregrid.toolbar.deleteSelectedFeatures"
disabled={disableToolbar}
visible={mode === "EDIT" && selectedCount > 0 && !hasChanges && !hasNewFeatures}
onClick={events.deleteFeatures}
glyph="trash-square"/>
<TButton
id="save-feature"
tooltip={<Message msgId={getSaveMessageId({saving, saved})}/>}
key="save-feature"
tooltipId={getSaveMessageId({saving, saved})}
disabled={saving || saved || disableToolbar}
visible={mode === "EDIT" && hasChanges || hasNewFeatures}
active={saved}
onClick={events.saveChanges}
glyph="floppy-disk"/>
<TButton
id="cancel-editing"
tooltip={<Message msgId="featuregrid.toolbar.cancelChanges"/>}
key="cancel-editing"
tooltipId="featuregrid.toolbar.cancelChanges"
disabled={disableToolbar}
visible={mode === "EDIT" && hasChanges || hasNewFeatures}
onClick={events.clearFeatureEditing}
glyph="remove-square"/>
<TButton
id="delete-geometry"
tooltip={<Message msgId="featuregrid.toolbar.deleteGeometry"/>}
key="delete-geometry"
tooltipId="featuregrid.toolbar.deleteGeometry"
disabled={disableToolbar}
visible={mode === "EDIT" && hasGeometry && selectedCount === 1 && hasSupportedGeometry}
onClick={events.deleteGeometry}
glyph="polygon-trash"/>
<TButton
id="download-grid"
tooltip={<Message msgId="featuregrid.toolbar.downloadGridData"/>}
key="download-grid"
tooltipId="featuregrid.toolbar.downloadGridData"
disabled={disableToolbar || disableDownload}
active={isDownloadOpen}
visible={displayDownload && mode === "VIEW"}
onClick={events.download}
glyph="features-grid-download"/>
<TButton
id="grid-settings"
tooltip={<Message msgId="featuregrid.toolbar.hideShowColumns"/>}
key="grid-settings"
tooltipId="featuregrid.toolbar.hideShowColumns"
disabled={disableToolbar}
active={isColumnsOpen}
visible={selectedCount <= 1 && mode === "VIEW"}
onClick={events.settings}
glyph="features-grid-set"/>
<TButton
id="grid-map-filter"
tooltip={<Message msgId="featuregrid.toolbar.syncOnMap"/>}
disabled={disableToolbar}
active={isSyncActive}
visible={mode === "VIEW"}
onClick={events.sync}
glyph="map-filter"/>
<TButton
id="grid-map-chart"
tooltip={<Message msgId="featuregrid.toolbar.createNewChart"/>}
key="grid-map-chart"
tooltipId="featuregrid.toolbar.createNewChart"
disabled={disableToolbar}
visible={mode === "VIEW" && showChartButton}
onClick={events.chart}
glyph="stats"/>
</ButtonGroup>);
<TButton
id="grid-map-filter"
key="grid-map-filter"
tooltipId="featuregrid.toolbar.syncOnMap"
disabled={disableToolbar}
active={isSyncActive}
visible={mode === "VIEW"}
onClick={events.sync}
glyph="map-filter"
renderPopover={syncPopover.showPopoverSync}
popoverOptions={{
placement: "top",
content: (<span>
<p><Message msgId="featuregrid.toolbar.synchPopoverText"/></p>
<p>
<Checkbox {...{checked: syncPopover.showAgain, onClick: events.toggleShowAgain}}>
<Message msgId="featuregrid.toolbar.notShowAgain"/>
</Checkbox>
</p>
</span>),
props: {
id: "sync-popover",
title: <div>
<Message msgId="featuregrid.toolbar.synchPopoverTitle"/>
<button onClick={() => {
if (syncPopover.showAgain) {
localStorage.setItem("showPopoverSync", false);
}
events.hideSyncPopover();
}} className="close">
<Glyphicon className="pull-right" glyph="1-close"/>
</button>
</div>,
style: {
bottom: syncPopover.dockSize
}
}}
} />

</ButtonGroup>); };
1 change: 0 additions & 1 deletion web/client/components/misc/enhancers/tooltip.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ const Message = require('../../I18N/Message');
*/
module.exports = branch(
({tooltip, tooltipId} = {}) => tooltip || tooltipId,
// TODO return proper HOC
(Wrapped) => ({tooltip, tooltipId, tooltipPosition = "top", tooltipTrigger, key, ...props} = {}) => (<OverlayTrigger
trigger={tooltipTrigger}
key={key}
Expand Down
2 changes: 1 addition & 1 deletion web/client/components/widgets/widget/InfoPopover.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class InfoPopover extends React.Component {
</OverlayTrigger>)
: [
this.renderContent(),
<Overlay show target={() => ReactDOM.findDOMNode(this.target)}>
<Overlay placement={this.props.placement} show target={() => ReactDOM.findDOMNode(this.target)}>
{this.renderPopover()}
</Overlay>
]}
Expand Down
3 changes: 2 additions & 1 deletion web/client/epics/maplayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ const updateMapLayoutEpic = (action$, store) =>
mapInfoRequestsSelector(store.getState()).length > 0 && {right: mapLayout.right.md} || null
].filter(panel => panel)) || {right: 0};

const bottom = isFeatureGridOpen(store.getState()) && {bottom: getDockSize(store.getState()) * 100 + '%'} || {bottom: mapLayout.bottom.sm};
const dockSize = getDockSize(store.getState()) * 100;
const bottom = isFeatureGridOpen(store.getState()) && {bottom: dockSize + '%', dockSize} || {bottom: mapLayout.bottom.sm};

const transform = isFeatureGridOpen(store.getState()) && {transform: 'translate(0, -' + mapLayout.bottom.sm + 'px)'} || {transform: 'none'};
const height = {height: 'calc(100% - ' + mapLayout.bottom.sm + 'px)'};
Expand Down
8 changes: 7 additions & 1 deletion web/client/plugins/featuregrid/panels/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ const {paginationInfo, featureLoadingSelector, resultsSelector, isSyncWmsActive,
const {getTitleSelector, modeSelector, selectedFeaturesCount, hasChangesSelector, hasGeometrySelector, isSimpleGeomSelector, hasNewFeaturesSelector, isSavingSelector, isSavedSelector, isDrawingSelector, canEditSelector, getAttributeFilter, hasSupportedGeometry, editingAllowedRolesSelector} = require('../../../selectors/featuregrid');
const {userRoleSelector} = require('../../../selectors/security');
const {isCesium} = require('../../../selectors/maptype');
const {chartDisabledSelector} = require('../../../selectors/featuregrid');
const {mapLayoutValuesSelector} = require('../../../selectors/mapLayout');
const {chartDisabledSelector, showAgainSelector, showPopoverSyncSelector} = require('../../../selectors/featuregrid');
const {deleteFeatures, toggleTool, clearChangeConfirmed, closeFeatureGridConfirmed, closeFeatureGrid} = require('../../../actions/featuregrid');
const {toolbarEvents, pageEvents} = require('../index');
const {getAttributeFields} = require('../../../utils/FeatureGridUtils');
Expand All @@ -35,6 +36,11 @@ const Toolbar = connect(
hasChanges: hasChangesSelector,
hasNewFeatures: hasNewFeaturesSelector,
hasGeometry: hasGeometrySelector,
syncPopover: state => ({
showAgain: showAgainSelector(state),
showPopoverSync: showPopoverSyncSelector(state),
dockSize: mapLayoutValuesSelector(state, {dockSize: true}).dockSize + 3.2 + "%"
}),
isDrawing: isDrawingSelector,
showChartButton: state => !chartDisabledSelector(state) && widgetBuilderAvailable(state),
isSimpleGeom: isSimpleGeomSelector,
Expand Down
Loading

0 comments on commit 17412f6

Please sign in to comment.