diff --git a/web/client/components/data/featuregrid/formatters/index.js b/web/client/components/data/featuregrid/formatters/index.js
index 28f2d339a6..5f2e4104e4 100644
--- a/web/client/components/data/featuregrid/formatters/index.js
+++ b/web/client/components/data/featuregrid/formatters/index.js
@@ -15,7 +15,7 @@ import NumberFormat from '../../../I18N/Number';
import { dateFormats as defaultDateFormats } from "../../../../utils/FeatureGridUtils";
const BooleanFormatter = ({value} = {}) => !isNil(value) ? {value.toString()} : null;
-const StringFormatter = ({value} = {}) => !isNil(value) ? reactStringReplace(value, /(https?:\/\/\S+)/g, (match, i) => (
+export const StringFormatter = ({value} = {}) => !isNil(value) ? reactStringReplace(value, /(https?:\/\/\S+)/g, (match, i) => (
{match}
)) : null;
const NumberFormatter = ({value} = {}) => !isNil(value) ? : null;
diff --git a/web/client/components/misc/enhancers/__tests__/handleLongTextEnhancer-test.jsx b/web/client/components/misc/enhancers/__tests__/handleLongTextEnhancer-test.jsx
new file mode 100644
index 0000000000..24faa3e6ea
--- /dev/null
+++ b/web/client/components/misc/enhancers/__tests__/handleLongTextEnhancer-test.jsx
@@ -0,0 +1,76 @@
+/**
+ * Copyright 2023, 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 { handleLongTextEnhancer } from '../handleLongTextEnhancer';
+import { StringFormatter } from '../../../data/featuregrid/formatters';
+
+describe("handleLongTextEnhancer enhancer", () => {
+ beforeEach((done) => {
+ document.body.innerHTML = '
';
+ setTimeout(done);
+ });
+
+ afterEach((done) => {
+ ReactDOM.unmountComponentAtNode(document.getElementById("container"));
+ document.body.innerHTML = '';
+ setTimeout(done);
+ });
+
+ it('handleLongTextEnhancer by passing formatter as wrapper', () => {
+ const EnhancerWithFormatter = ()=> handleLongTextEnhancer(StringFormatter)({ value: "test12334567899999" });
+ ReactDOM.render(
+ ,
+ document.getElementById("container")
+ );
+ expect(document.getElementById("container").innerHTML).toExist();
+ expect(document.getElementsByTagName('span').length).toEqual(2);
+ expect(document.getElementsByTagName('span')[1].innerHTML).toExist();
+ });
+
+ it('handleLongTextEnhancer with by passing td as wrapper', () => {
+ const wrapper = () => (15234568965 | );
+ const EnhancerWithFormatter = ()=> handleLongTextEnhancer(wrapper)({ value: "15234568965" });
+ ReactDOM.render(
+ ,
+ document.getElementById("container")
+ );
+ expect(document.getElementById("container").innerHTML).toExist();
+ expect(document.getElementsByTagName('span').length).toEqual(2);
+ expect(document.getElementsByTagName('span')[1].innerHTML).toExist();
+ });
+
+
+ it('handleLongTextEnhancer with by passing span as wrapper', () => {
+ const wrapper = () => (15234568965);
+ const EnhancerWithFormatter = ()=> handleLongTextEnhancer(wrapper)({ value: "15234568965" });
+ ReactDOM.render(
+ ,
+ document.getElementById("container")
+ );
+ expect(document.getElementById("container").innerHTML).toExist();
+ expect(document.getElementsByTagName('span').length).toEqual(3);
+ expect(document.getElementsByTagName('span')[1].innerHTML).toExist();
+ });
+
+
+ it('handleLongTextEnhancer with by passing td div wrapper', () => {
+ const wrapper = () => (test
);
+ const EnhancerWithFormatter = ()=> handleLongTextEnhancer(wrapper)({ value: "test" });
+ ReactDOM.render(
+ ,
+ document.getElementById("container")
+ );
+ expect(document.getElementById("container").innerHTML).toExist();
+ expect(document.getElementsByTagName('span').length).toEqual(2);
+ expect(document.getElementsByTagName('span')[1].innerHTML).toExist();
+ });
+});
diff --git a/web/client/components/misc/enhancers/handleLongTextEnhancer.jsx b/web/client/components/misc/enhancers/handleLongTextEnhancer.jsx
new file mode 100644
index 0000000000..7b75d8a321
--- /dev/null
+++ b/web/client/components/misc/enhancers/handleLongTextEnhancer.jsx
@@ -0,0 +1,50 @@
+/*
+* Copyright 2023, 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 OverlayTrigger from "../OverlayTrigger";
+import { Tooltip } from "react-bootstrap";
+/**
+ * handleLongTextEnhancer enhancer. Enhances a long text content by adding a tooltip.
+ * @type {function}
+ * @name handleLongTextEnhancer
+ * @memberof components.misc.enhancers
+ * Wraps [wrapped component with content] to add tooltip for long content if shown content less than the main content
+ * @param {Component} Wrapped the component wrapped with a tooltip when its content is too long
+ * @param {object} props the props that contains value content
+ * @return {Component} the rendered component that renders the content with the tooltip if the content is long or renders the content with no tooltip if not long
+ * @example
+ * const wrapper = () = > testtttttttttt
+ * const Component = ()=> handleLongTextEnhancer(wrapper)(props);
+ * render (){
+ * return
+ * }
+ *
+ */
+export const handleLongTextEnhancer = (Wrapped) => (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;
+ setIsContentOverflowing(contentWidth > cellWidth);
+ };
+
+ return ({} : <>>}
+ >
+
+
+ {}
+
+
+ );
+};
diff --git a/web/client/utils/FeatureGridUtils.js b/web/client/utils/FeatureGridUtils.js
index 19e41a2643..190f62cb91 100644
--- a/web/client/utils/FeatureGridUtils.js
+++ b/web/client/utils/FeatureGridUtils.js
@@ -18,6 +18,7 @@ import {
} from './ogc/WFS/base';
import { applyDefaultToLocalizedString } from '../components/I18N/LocalizedString';
+import { handleLongTextEnhancer } from '../components/misc/enhancers/handleLongTextEnhancer';
const getGeometryName = (describe) => get(findGeometryProperty(describe), "name");
const getPropertyName = (name, describe) => name === "geometry" ? getGeometryName(describe) : name;
@@ -115,6 +116,7 @@ export const getCurrentPaginationOptions = ({ startPage, endPage }, oldPages, si
return { startIndex: nPs[0] * size, maxFeatures: needPages * size };
};
+
/**
* Utility function to get from a describeFeatureType response the columns to use in the react-data-grid
* @param {object} describe describeFeatureType response
@@ -146,7 +148,7 @@ export const featureTypeToGridColumns = (
editable,
filterable,
editor: getEditor(desc, field),
- formatter: getFormatter(desc, field),
+ formatter: handleLongTextEnhancer(getFormatter(desc, field)),
filterRenderer: getFilterRenderer(desc, field)
};
});
diff --git a/web/client/utils/__tests__/FeatureGridUtils-test.js b/web/client/utils/__tests__/FeatureGridUtils-test.js
index 68d081aca3..aafbbac3ea 100644
--- a/web/client/utils/__tests__/FeatureGridUtils-test.js
+++ b/web/client/utils/__tests__/FeatureGridUtils-test.js
@@ -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,
@@ -18,6 +21,18 @@ import {
describe('FeatureGridUtils', () => {
+ beforeEach((done) => {
+ document.body.innerHTML = '';
+ 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);
@@ -332,6 +347,26 @@ 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 DUMMY = () => {};
+ const formatterWrapper = () => (testtttt
);
+ const describe = {featureTypes: [{properties: [{name: 'Test1', type: "xsd:number"}, {name: 'Test2', type: "xsd:number"}]}]};
+ const columnSettings = {name: 'Test1', hide: false};
+ const options = [{name: 'Test1', title: 'Some title', description: 'Some description'}];
+ const featureGridColumns = featureTypeToGridColumns(describe, columnSettings, [], {options}, {getHeaderRenderer: () => DUMMY, getFilterRenderer: () => DUMMY, getFormatter: () => formatterWrapper, getEditor: () => DUMMY});
+ expect(featureGridColumns.length).toBe(2);
+ featureGridColumns.forEach((fgColumns)=>{
+ const Formatter = fgColumns.formatter;
+ ReactDOM.render(
+ ,
+ 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', () => {