Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#9553: Improving readability of long attribute values in attribute table and table widgets #9701

Merged
merged 8 commits into from
Nov 21, 2023
Next Next commit
#9553: handle showing tooltip on attr table cells once user hovers on…
… cell
  • Loading branch information
mahmoudadel54 committed Nov 14, 2023
commit 5be7fab359b8873c257e69469dd4236795700bb4
34 changes: 33 additions & 1 deletion web/client/utils/FeatureGridUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import {
} from './ogc/WFS/base';

import { applyDefaultToLocalizedString } from '../components/I18N/LocalizedString';
import React from 'react';
import OverlayTrigger from '../components/misc/OverlayTrigger';
import { Tooltip } from 'react-bootstrap';

const getGeometryName = (describe) => get(findGeometryProperty(describe), "name");
const getPropertyName = (name, describe) => name === "geometry" ? getGeometryName(describe) : name;
Expand Down Expand Up @@ -115,6 +118,35 @@ export const getCurrentPaginationOptions = ({ startPage, endPage }, oldPages, si
return { startIndex: nPs[0] * size, maxFeatures: needPages * size };
};


const formatterWrapperForLongContent = (props, RenderFormatter) => {
const { value } = props;
const cellRef = React.useRef(null);
const contentRef = React.useRef(null);
const [isContentOverflowing, setIsContentOverflowing] = React.useState(false);

const handleMouseEnter = () => {
const cellWidth = cellRef.current.offsetWidth;
const contentWidth = contentRef.current.offsetWidth;

if (contentWidth > cellWidth) {
setIsContentOverflowing(contentWidth > cellWidth);
} else setIsContentOverflowing(false);
};

return (<OverlayTrigger
placement="top"
overlay={isContentOverflowing ? <Tooltip id="tooltip">{RenderFormatter ? <RenderFormatter {...props} /> : value}</Tooltip> : <></>}
>
<div ref={cellRef} onMouseEnter={handleMouseEnter}>
<span ref={contentRef}>
<span>{RenderFormatter ? <RenderFormatter {...props} /> : value}</span>
</span>
</div>
</OverlayTrigger>);
};


/**
* Utility function to get from a describeFeatureType response the columns to use in the react-data-grid
* @param {object} describe describeFeatureType response
Expand Down Expand Up @@ -146,7 +178,7 @@ export const featureTypeToGridColumns = (
editable,
filterable,
editor: getEditor(desc, field),
formatter: getFormatter(desc, field),
formatter: (props_) => formatterWrapperForLongContent(props_, getFormatter(desc, field)),
filterRenderer: getFilterRenderer(desc, field)
};
});
Expand Down
41 changes: 41 additions & 0 deletions web/client/utils/__tests__/FeatureGridUtils-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
* 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 ReactDOM from "react-dom";
import expect from 'expect';

import {
updatePages,
gridUpdateToQueryUpdate,
Expand All @@ -18,6 +21,18 @@ import {


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

afterEach((done) => {
ReactDOM.unmountComponentAtNode(
document.getElementById("container")
);
document.body.innerHTML = "";
setTimeout(done);
});
it('Test updatePages when needPages * size is less then features', () => {
const oldFeatures = Array(350);
const features = Array(60);
Expand Down Expand Up @@ -332,6 +347,32 @@ describe('FeatureGridUtils', () => {
// test localized alias with empty default
expect(featureTypeToGridColumns(describe, columnSettings, [{name: "Test1", alias: {"default": ""}}])[0].title.default).toEqual('Test1');

});
it('featureTypeToGridColumns formatters', () => {
const describe = {featureTypes: [{properties: [{name: 'Test1', type: "xsd:number"}, {name: 'Test2', type: "xsd:number"}, {name: 'Test3', type: "xsd:string"}]}]};
const columnSettings = {name: 'Test1', hide: false};
const fields = [{name: 'Test1', type: "xsd:number", alias: 'Test1 alias'}];
const featureGridColumns = featureTypeToGridColumns(describe, columnSettings, fields);
expect(featureGridColumns.length).toBe(3);
expect(featureGridColumns[0].title).toBe('Test1 alias');
// test alias empty string
expect(featureTypeToGridColumns(describe, columnSettings, [{name: "Test1", alias: ""}])[0].title).toEqual('Test1');
// test localized alias
expect(featureTypeToGridColumns(describe, columnSettings, [{name: "Test1", alias: {"default": "XX"}}])[0].title.default).toEqual('XX');
// test localized alias with empty default
expect(featureTypeToGridColumns(describe, columnSettings, [{name: "Test1", alias: {"default": ""}}])[0].title.default).toEqual('Test1');
const values = [123456, 12.3256, "test"];
featureGridColumns.forEach((fgColumns, index)=>{
const Formatter = fgColumns.formatter;
ReactDOM.render(
<Formatter value={values[index]} />,
document.getElementById("container")
);
expect(document.getElementById("container").innerHTML).toExist();
expect(document.getElementsByTagName('span').length).toEqual(2);
expect(document.getElementsByTagName('span')[1].innerHTML).toExist();
});

});
describe("supportsFeatureEditing", () => {
it('test supportsFeatureEditing with valid layer type', () => {
Expand Down