Skip to content

Commit

Permalink
geosolutions-it#7332: Identify for annotations is showing all interna…
Browse files Browse the repository at this point in the history
…l properties rather than title/description (geosolutions-it#7443)

* refactor of identify property viewer

* remove properties from vector map info

* remove hideToolbar prop
  • Loading branch information
allyoucanmap committed Oct 14, 2021
1 parent aec1ead commit 3ab6b1a
Show file tree
Hide file tree
Showing 12 changed files with 247 additions and 98 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@

import React from 'react';

import PropertiesViewer from './row/PropertiesViewer';
import RowViewer from './row/RowViewer';

export default ({response, layer, rowViewer}) => {
const RowViewer = (layer && layer.rowViewer) || rowViewer || PropertiesViewer;
return (
<div className="mapstore-json-viewer">
{(response?.features || []).map((feature, i) => {
return <RowViewer key={i} feature={feature} title={feature.id + ''} exclude={["bbox"]} {...feature.properties}/>;
return <RowViewer key={i} feature={feature} layer={layer} component={rowViewer}/>;
})}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,73 +6,72 @@
* LICENSE file in the root directory of this source tree.
*/

import {isString} from 'lodash';
import { isString } from 'lodash';
import PropTypes from 'prop-types';
import React from 'react';

import {containsHTML} from '../../../../../utils/StringUtils';

const alwaysExcluded = ["exclude", "titleStyle", "listStyle", "componentStyle", "title", "feature"];

import { containsHTML } from '../../../../../utils/StringUtils';
import Message from '../../../../I18N/Message';
class PropertiesViewer extends React.Component {
static displayName = 'PropertiesViewer';

static propTypes = {
title: PropTypes.string,
exclude: PropTypes.array,
include: PropTypes.array,
titleStyle: PropTypes.object,
listStyle: PropTypes.object,
componentStyle: PropTypes.object
componentStyle: PropTypes.object,
feature: PropTypes.object,
labelIds: PropTypes.object
};

static defaultProps = {
exclude: [],
titleStyle: {},
listStyle: {},
componentStyle: {}
componentStyle: {},
labelIds: {}
};

getBodyItems = () => {
return Object.keys(this.props)
.filter(this.toExclude)
return Object.keys(this.props?.feature?.properties || {})
.filter(this.props?.include?.length > 0 ? this.toInclude : this.toExclude)
.map((key) => {
const val = this.renderProperty(this.props[key]);
const val = this.renderProperty(this.props.feature.properties[key]);
return (
<tr
<li
key={key}
style={this.props.listStyle}>
<td>{key}</td>
<td>{containsHTML(val) ? <span dangerouslySetInnerHTML={{__html: val}}/> : val}</td>
</tr>);
<div className="ms-properties-viewer-key">{this.props.labelIds[key] ? <Message msgId={this.props.labelIds[key]}/> : key}</div>
{containsHTML(val) ? <div className="ms-properties-viewer-value" dangerouslySetInnerHTML={{__html: val}}/> : <div className="ms-properties-viewer-value">{val}</div>}
</li>);
});
};

renderHeader = () => {
if (!this.props.title) {
if (this.props.feature?.id === undefined) {
return null;
}
const title = this.props.feature.id + '';
return (
<thead
key={this.props.title}
<div
key={title}
style={this.props.titleStyle}
className="ms-properties-viewer-title">
<tr>
<th colSpan="2" >{this.props.title}</th>
</tr>
</thead>
{title}
</div>
);
};

renderBody = () => {
var items = this.getBodyItems();
const items = this.getBodyItems();
if (items.length === 0) {
return null;
}
return (
<tbody
<ul
className="ms-properties-viewer-body">
{items}
</tbody>
</ul>
);
};

Expand All @@ -85,20 +84,24 @@ class PropertiesViewer extends React.Component {

render() {
return (
<table
<div
className="ms-properties-viewer"
style={this.props.componentStyle}>
{this.renderHeader()}
{this.renderBody()}
</table>
</div>
);
}

toExclude = (propName) => {
return alwaysExcluded
.concat(this.props.exclude)
return this.props.exclude
.indexOf(propName) === -1;
};

toInclude = (propName) => {
return this.props.include
.indexOf(propName) !== -1;
};
}

export default PropertiesViewer;
64 changes: 64 additions & 0 deletions web/client/components/data/identify/viewers/row/RowViewer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2021, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import { isString } from 'lodash';
import PropertiesViewer from './PropertiesViewer';
import { getRowViewer } from '../../../../../utils/MapInfoUtils';
import { ANNOTATIONS } from '../../../../../utils/AnnotationsUtils';
import PropTypes from 'prop-types';

const defaultRowViewerOptions = {
// we need some default options for annotations
// to ensure that only title and description are displayed
// when the custom row viewer is not mounted
[ANNOTATIONS]: {
include: ['title', 'description'],
labelIds: {
title: 'annotations.field.title',
description: 'annotations.field.description'
}
}
};

function RowViewer({
layer,
component,
feature
}) {
// the name of the registered viewer could be associate by a string in the rowViewer or id
const layerRowViewerProperty = layer?.rowViewer || layer?.layerId;
const defaultOptions = isString(layerRowViewerProperty) ? defaultRowViewerOptions[layerRowViewerProperty] : {};
const excludeProperties = defaultOptions?.exclude ? defaultOptions.exclude : ['bbox'];
const includeProperties = defaultOptions?.include;
const labelIds = defaultOptions?.labelIds;
const layerRowViewer = isString(layerRowViewerProperty) ? getRowViewer(layerRowViewerProperty) : layerRowViewerProperty;
const Row = layerRowViewer || component || PropertiesViewer;
return (
<Row
{...feature.properties}
feature={feature}
labelIds={labelIds}
exclude={excludeProperties}
include={includeProperties}
/>
);
}

RowViewer.propTypes = {
layer: PropTypes.string,
component: PropTypes.array,
feature: PropTypes.array
};

RowViewer.defaultProps = {
layer: {},
feature: {}
};

export default RowViewer;
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,23 @@ describe('PropertiesViewer', () => {
setTimeout(done);
});
it('test defaults', () => {
const cmp = ReactDOM.render(<PropertiesViewer/>, document.getElementById("container"));
expect(cmp).toExist();

const cmpDom = ReactDOM.findDOMNode(cmp);
expect(cmpDom).toExist();

expect(cmpDom.childNodes.length).toBe(0);
ReactDOM.render(<PropertiesViewer/>, document.getElementById("container"));
const viewerNode = document.querySelector('.ms-properties-viewer');
expect(viewerNode).toBeTruthy();
});
it('test title rendering', () => {
ReactDOM.render(<PropertiesViewer title="testTitle"/>, document.getElementById("container"));
ReactDOM.render(<PropertiesViewer feature={{ id: "testTitle" }}/>, document.getElementById("container"));
const titleNode = document.querySelector('.ms-properties-viewer-title');
expect(titleNode).toBeTruthy();
expect(titleNode.querySelector('th').innerHTML).toBe("testTitle");
expect(titleNode.innerHTML).toBe("testTitle");
});
it('test body rendering', () => {
const testProps = {
k0: "v0",
k1: "v1",
k2: "v2"
};
const cmp = ReactDOM.render(<PropertiesViewer {...testProps}/>, document.getElementById("container"));
const cmp = ReactDOM.render(<PropertiesViewer feature={{ properties: testProps }}/>, document.getElementById("container"));
expect(cmp).toBeTruthy();

const cmpDom = ReactDOM.findDOMNode(cmp);
Expand All @@ -59,41 +55,22 @@ describe('PropertiesViewer', () => {
expect(Array.prototype.reduce.call(body.childNodes, (prev, child, i) => {
let testKey = testKeys[i];
let testVal = testProps[testKey];
const rowData = child.querySelectorAll('td');
const rowData = child.querySelectorAll('div');
const key = rowData[0].innerHTML;
const value = rowData[1].innerHTML;
return prev
&& key === testKey && value === testVal;
}, true)).toBe(true);
});

it('test feature isexcluded', () => {
const cmp = ReactDOM.render(<PropertiesViewer feature={"myfeature"} title="testTitle" />, document.getElementById("container"));
expect(cmp).toExist();

const cmpDom = ReactDOM.findDOMNode(cmp);
expect(cmpDom).toExist();

expect(cmpDom.innerText.indexOf('myfeature')).toBe(-1);
});


it('test rendering an html property', () => {
const testProps = {
withHtml: "<div> some text </div>"
withHtml: "<p id=\"rendered-html\">some text</p>"
};
const cmp = ReactDOM.render(<PropertiesViewer {...testProps}/>, document.getElementById("container"));
expect(cmp).toBeTruthy();

const cmpDom = ReactDOM.findDOMNode(cmp);
expect(cmpDom).toBeTruthy();
expect(cmpDom.children.length).toBe(1);

const body = cmpDom.children[0];

const tdChildren = body.querySelectorAll('td');
const spanChild = tdChildren[1].querySelector('span');
expect(spanChild).toBeTruthy();
expect(spanChild.innerHTML).toBe(testProps.withHtml);
ReactDOM.render(<PropertiesViewer feature={{ properties: testProps }}/>, document.getElementById("container"));
const viewerBodyNode = document.querySelector('.ms-properties-viewer-body');
const renderedPNode = viewerBodyNode.querySelector('#rendered-html');
expect(renderedPNode).toBeTruthy();
expect(renderedPNode.innerHTML).toBe('some text');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* Copyright 2015, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

import expect from 'expect';
import React from 'react';
import ReactDOM from 'react-dom';
import RowViewer from '../RowViewer';
import { ANNOTATIONS } from '../../../../../../utils/AnnotationsUtils';
import { registerRowViewer } from '../../../../../../utils/MapInfoUtils';

describe('RowViewer', () => {
beforeEach((done) => {
document.body.innerHTML = '<div id="container"></div>';
setTimeout(done);
});

afterEach((done) => {
ReactDOM.unmountComponentAtNode(document.getElementById("container"));
document.body.innerHTML = '';
setTimeout(done);
});
it('should render with default', () => {
ReactDOM.render(<RowViewer />, document.getElementById("container"));
const viewerNode = document.querySelector('.ms-properties-viewer');
expect(viewerNode).toBeTruthy();
});
it('should apply default option for annotation layer', () => {

const TestComponent = ({
include
}) => {
return <div id="annotation-include-option">{include.join()}</div>;
};

ReactDOM.render(
<RowViewer
layer={{ layerId: ANNOTATIONS }}
component={TestComponent}
feature={{ properties: {}, id: 'feature' }}
/>,
document.getElementById("container"));

const includeOptionNode = document.querySelector('#annotation-include-option');
expect(includeOptionNode.innerHTML).toBe('title,description');
});

it('should render the registered row viewer', () => {

const RegisteredComponent = () => {
return <div id="registered-viewer"></div>;
};

registerRowViewer(ANNOTATIONS, RegisteredComponent);

ReactDOM.render(
<RowViewer
layer={{ layerId: ANNOTATIONS }}
feature={{ properties: {}, id: 'feature' }}
/>,
document.getElementById("container"));

const registeredViewerNode = document.querySelector('#registered-viewer');
expect(registeredViewerNode).toBeTruthy();

registerRowViewer(ANNOTATIONS, undefined);
});
});
2 changes: 1 addition & 1 deletion web/client/epics/__tests__/annotations-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const {
setAnnotationStyleEpic, restoreStyleEpic, highlightAnnotationEpic, cleanHighlightAnnotationEpic, closeAnnotationsEpic, confirmCloseAnnotationsEpic,
downloadAnnotations, onLoadAnnotations, onChangedSelectedFeatureEpic, onBackToEditingFeatureEpic, redrawOnChangeRadiusEpic, redrawOnChangeTextEpic,
editSelectedFeatureEpic, editCircleFeatureEpic, purgeMapInfoEpic, closeMeasureToolEpic, openEditorEpic, loadDefaultAnnotationsStylesEpic, showHideAnnotationEpic, hideAnnotationGroupEpic, highlightGeometryEpic
} = annotationsEpics({});
} = annotationsEpics;

const rootEpic = combineEpics(addAnnotationsLayerEpic, editAnnotationEpic, removeAnnotationEpic, setEditingFeatureEpic, saveAnnotationEpic, newAnnotationEpic, addAnnotationEpic,
disableInteractionsEpic, cancelEditAnnotationEpic, startDrawingMultiGeomEpic, endDrawGeomEpic,
Expand Down
Loading

0 comments on commit 3ab6b1a

Please sign in to comment.