Skip to content

Commit

Permalink
Fix #9381 image featureinfo (#9435) (#9488)
Browse files Browse the repository at this point in the history
# Conflicts:
#	web/client/themes/default/less/common.less
  • Loading branch information
MV88 authored Sep 26, 2023
1 parent 215931b commit 9c8e34e
Show file tree
Hide file tree
Showing 14 changed files with 126 additions and 13 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,12 @@
"react-copy-to-clipboard": "5.0.0",
"react-data-grid": "5.0.4",
"react-data-grid-addons": "5.0.4",
"react-draft-wysiwyg": "npm:@geosolutions/[email protected]",
"react-dnd": "2.6.0",
"react-dnd-html5-backend": "2.6.0",
"react-dnd-test-backend": "2.6.0",
"react-dock": "0.2.4",
"react-dom": "16.10.1",
"react-draft-wysiwyg": "npm:@geosolutions/[email protected]",
"react-draggable": "2.2.6",
"react-dropzone": "3.13.1",
"react-error-boundary": "1.2.5",
Expand Down
45 changes: 41 additions & 4 deletions web/client/components/TOC/fragments/settings/FeatureInfoEditor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
* LICENSE file in the root directory of this source tree.
*/

import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { createPortal } from 'react-dom';
import PropTypes from 'prop-types';

import Message from '../../../I18N/Message';
Expand All @@ -15,6 +16,7 @@ import ResizableModal from '../../../misc/ResizableModal';
import CompactRichTextEditor from '../../../mapviews/settings/CompactRichTextEditor';
import withDebounceOnCallback from '../../../misc/enhancers/withDebounceOnCallback';
import { htmlToDraftJSEditorState, draftJSEditorStateToHtml } from '../../../../utils/EditorUtils';
import { getMessageById } from '../../../../utils/LocaleUtils';

const DescriptionEditor = withDebounceOnCallback('onEditorStateChange', 'editorState')(CompactRichTextEditor);
/**
Expand All @@ -35,19 +37,40 @@ const FeatureInfoEditor = ({
onShowEditor,
onChange,
enableIFrameModule
}) => {
}, {messages}) => {
const [, setCounter] = useState(0);
useEffect(() => {
const imageButton = document.querySelector(".rdw-image-wrapper");
const clickImageToolbarListener = () => {
setTimeout(() => {
setCounter(value => value + 1);
});
};
if (imageButton) {
imageButton.addEventListener("click", clickImageToolbarListener);
}
return () => {
if (imageButton) {
imageButton?.removeEventListener("click", clickImageToolbarListener);
}
};

const [editorState, setEditorState] = useState(htmlToDraftJSEditorState(element?.featureInfo?.template || ''));
}, [showEditor]);

const [template, setTemplate] = useState(element?.featureInfo?.template || '');
const [editorState, setEditorState] = useState(htmlToDraftJSEditorState(template));
const onClose = () => {
onShowEditor(!showEditor);
onChange('featureInfo', {
...(element && element.featureInfo || {}),
template: draftJSEditorStateToHtml(editorState)
});
};
const imageField = document.querySelector(".rdw-image-modal-url-section");
return (
<Portal>
<ResizableModal
modalClassName="ms-feature-info-editor"
fade
show={showEditor}
title={<Message msgId="layerProperties.editCustomFormat"/>}
Expand All @@ -63,14 +86,25 @@ const FeatureInfoEditor = ({
}
]}>
<div id="ms-template-editor" className="ms-editor">
<style dangerouslySetInnerHTML={{__html: ".DraftEditor-editorContainer img::after {content: '" + getMessageById(messages, "layerProperties.imageNotFound") + "'}"} }/>
{imageField ? createPortal(<div className="guide-text"><Message msgId="layerProperties.guideText"/></div>, imageField) : null}

<DescriptionEditor
toolbarOptions={['fontFamily', 'blockType', 'inline', 'textAlign', 'list', 'link', 'colorPicker', 'remove', 'image'].concat(enableIFrameModule ? ['embedded'] : [])}
editorState={editorState}
onEditorStateChange={(newEditorState) => {
const previousHTML = draftJSEditorStateToHtml(editorState);
const images = document.querySelectorAll(".DraftEditor-editorContainer img");
const newHTML = draftJSEditorStateToHtml(newEditorState);
for (const img of images) {
// an alt value is needed for firefox to show the ::after and ::after pseudo elements
// empty space to avoid to show the alt value
// this is a different behaviour from chrome
img.alt = " ";

}
if (newHTML !== previousHTML) {
onChange({ template: draftJSEditorStateToHtml(newEditorState) });
setTemplate(draftJSEditorStateToHtml(newEditorState));
setEditorState(newEditorState);
}
}}
Expand All @@ -88,6 +122,9 @@ FeatureInfoEditor.propTypes = {
onShowEditor: PropTypes.func,
enableIFrameModule: PropTypes.bool
};
FeatureInfoEditor.contextTypes = {
messages: PropTypes.object
};

FeatureInfoEditor.defaultProps = {
showEditor: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import Message from '../../../I18N/Message';

const TemplateViewer = ({layer = {}, response}) => (
<div className="ms-template-viewer">
{response.features.map((feature, i) => {
{response?.features?.map((feature, i) => {
const cleanTemplate = getCleanTemplate(layer.featureInfo && layer.featureInfo.template || '', feature, /\$\{.*?\}/g, 2, 1);
let html = "";
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ function CompactRichTextEditor({
}),
previewImage: true,
inputAccept: 'image/gif,image/jpeg,image/jpg,image/png,image/svg',
alt: { present: false, mandatory: false },
alt: props.alt || { present: false, mandatory: false },
defaultSize: {
height: 'auto',
width: '100%'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const formatCards = {
descId: 'layerProperties.templateFormatDescription',
glyph: 'ext-empty',
body: ({ template = '', ...props }) => (
<div>
<div className="template-html-renderer" >
<div>{template && template !== '<p><br></p>' ? <Message msgId="layerProperties.templatePreview" /> : null}</div>
<br />
<div>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 64 additions & 0 deletions web/client/themes/default/less/common.less
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// LICENSE file in the root directory of this source tree.
//


// **************
// Theme
// **************
Expand Down Expand Up @@ -67,6 +68,14 @@
.background-color-var(@theme-vars[success]);
.color-var(@theme-vars[primary-contrast]);
}
.DraftEditor-editorContainer,
.template-html-renderer,
.ms-template-viewer
{
img::before {
.background-color-var(@theme-vars[main-bg]);
}
}
}

// **************
Expand Down Expand Up @@ -332,3 +341,58 @@ div#sync-popover.popover {
}
}
}


.ms-feature-info-editor {
.rdw-image-modal-url-section {
display: block;
}
.guide-text {
font-size: @font-size-small;
font-style: italic;
}
}


.DraftEditor-editorContainer, // selector editor
.template-html-renderer, // selector preview sx
.ms-template-viewer // selector fi panel
{
img {
display: inline-block;
min-height: 145px;
position: relative;
text-align: center;
min-width: 460px;
max-width: 100%;
font-size: @font-size-small;
}
img::before {
content: ' ';
width: 101%;
height: calc(100% - 36px);
border-radius: 10px;
position: absolute;
top: -2px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
left: -2px;
background-image: url("../img/image-not-found.jpg");
}

img::after {
font-size: @font-size-small;
display: block;
bottom: 0;
left: 50%;
font-style: italic;
position: absolute;
transform: translate(-50%, 0px);
}
}

.form-control.intl-numeric {
float: unset;

}
2 changes: 2 additions & 0 deletions web/client/translations/data.de-DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@
"groupProperties": "Gruppeneigenschaften",
"featureInfo": "Feature Info",
"featureInfoFormatLbl": "Antwortformat festlegen",
"guideText": "In der URL des Bildes können Sie Platzhalter wie $\\{properties.YOUR_ATTRIBUTE\\} verwenden, um die URL abhängig von den Feature-Attributen parametrisch zu machen. Es unterstützt sowohl URLs als auch „Data URI“, die in Base64 codiert sind",
"imageNotFound": "Für die korrekte Darstellung dieses Bildes ist möglicherweise eine Feature-Info-Anfrage erforderlich",
"legenderror": "Legende ist nicht verfügbar",
"editCustomFormat": "Bearbeiten Sie das benutzerdefinierte Format",
"exampleOfResponse": "Beispiel",
Expand Down
2 changes: 2 additions & 0 deletions web/client/translations/data.en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@
"groupProperties": "Group properties",
"featureInfo": "Feature Info",
"featureInfoFormatLbl": "Identify response format",
"guideText": "In the URL of the image you can use placeholders like $\\{properties.YOUR_ATTRIBUTE\\} to make the URL parametric, depending by the feature attributes. It supports both URLs or \"Data URIs\" encoded in base64",
"imageNotFound": "This image may need a feature info request to be rendered correctly",
"legenderror": "Legend is not available",
"editCustomFormat": "Edit custom format",
"exampleOfResponse": "Example",
Expand Down
2 changes: 2 additions & 0 deletions web/client/translations/data.es-ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@
"groupProperties": "Propiedades del grupo",
"featureInfo": "Información de la capa",
"featureInfoFormatLbl": "Identificar el formato de respuesta",
"guideText": "En la URL de la imagen, puede utilizar marcadores de posición como $\\{properties.YOUR_ATTRIBUTE\\} para hacer que la URL sea paramétrica, según los atributos de la característica. Admite URL o \"Data URI\" codificados en base64",
"imageNotFound": "Es posible que esta imagen necesite una solicitud de información de función para renderizarse correctamente",
"legenderror": "La leyenda no está disponible",
"editCustomFormat": "Editar formato personalizado",
"exampleOfResponse": "Ejemplo",
Expand Down
2 changes: 2 additions & 0 deletions web/client/translations/data.fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@
"groupProperties": "Propriétés du groupe",
"featureInfo": "Informations attributaires de l'objet",
"featureInfoFormatLbl": "Information, format de la réponse",
"guideText": "Dans l'URL de l'image, vous pouvez utiliser des espaces réservés comme $\\{properties.YOUR_ATTRIBUTE\\} pour rendre l'URL paramétrique, en fonction des attributs de la fonctionnalité. Il prend en charge à la fois les URL ou les « Data URI » codés en base64.",
"imageNotFound": "Cette image peut nécessiter une demande d'informations sur les fonctionnalités pour être rendue correctement",
"legenderror": "La légende n'est pas disponible",
"editCustomFormat": "Modifier le format personnalisé",
"exampleOfResponse": "Exemple",
Expand Down
2 changes: 2 additions & 0 deletions web/client/translations/data.it-IT.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@
"groupProperties": "Proprietà del gruppo",
"featureInfo": "Feature Info",
"featureInfoFormatLbl": "Formato risposta interrogazioni su mappa",
"guideText": "Nell'URL dell'immagine puoi utilizzare variabili come $\\{properties.YOUR_ATTRIBUTE\\} per rendere parametrico l'URL a seconda degli attributi della feature. Supporta sia URL che \"Data URI\" codificati in base64",
"imageNotFound": "Questa immagine può necessitare di una richiesta informazioni sulle feature per essere renderizzata correttamente",
"legenderror": "Legenda non disponibile",
"editCustomFormat": "Edita formato",
"exampleOfResponse": "Esempio",
Expand Down
4 changes: 3 additions & 1 deletion web/client/utils/EditorUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ContentState, EditorState, convertToRaw, Entity } from 'draft-js';
import draftToHtml from 'draftjs-to-html';
import htmlToDraft from 'html-to-draftjs';


// customGetEntityId is a utility function used by html-to-draftjs library in order
// to create anhor tag chunks
export const customGetEntityId = (node) => {
Expand Down Expand Up @@ -79,7 +80,8 @@ export const customEntityTransform = (entity, text) => {
'display: block; margin: 0 auto 0 auto;' :
`float: ${alignment};`;

return `<img src="${entity.data.src}" alt="${entity.data.alt}" style="height: ${entity.data.height}; width: ${entity.data.width}; ${alignmentStyle}" />`;
// on error will replace value of src and we have to keep original value that we can replace in the template viewer
return `<img title="${entity.data.src}" src="${entity.data.src}" alt="${entity.data.alt || " "}" style="height: ${entity.data.height}; width: ${entity.data.width}; ${alignmentStyle}"/>`;
}

if (entity.type === 'EMBEDDED_LINK') {
Expand Down
8 changes: 4 additions & 4 deletions web/client/utils/__tests__/EditorUtils-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('Test the EditorUtils', () => {
}
};

const expectedResult = '<img src="http://src" alt="alternative" style="height: 128px; width: 128px; display: block; margin: 0 auto 0 auto;" />';
const expectedResult = '<img title="http://src" src="http://src" alt="alternative" style="height: 128px; width: 128px; display: block; margin: 0 auto 0 auto;"/>';
const result = customEntityTransform(entity);

expect(result).toBe(expectedResult);
Expand All @@ -54,7 +54,7 @@ describe('Test the EditorUtils', () => {
}
};

const expectedResult = '<img src="http://src" alt="alternative" style="height: 128px; width: 128px; display: block; margin: 0 auto 0 auto;" />';
const expectedResult = '<img title="http://src" src="http://src" alt="alternative" style="height: 128px; width: 128px; display: block; margin: 0 auto 0 auto;"/>';
const result = customEntityTransform(entity);

expect(result).toBe(expectedResult);
Expand All @@ -71,7 +71,7 @@ describe('Test the EditorUtils', () => {
}
};

const expectedResult = '<img src="http://src" alt="alternative" style="height: 128px; width: 128px; float: left;" />';
const expectedResult = '<img title="http://src" src="http://src" alt="alternative" style="height: 128px; width: 128px; float: left;"/>';
const result = customEntityTransform(entity);

expect(result).toBe(expectedResult);
Expand All @@ -88,7 +88,7 @@ describe('Test the EditorUtils', () => {
}
};

const expectedResult = '<img src="http://src" alt="alternative" style="height: 128px; width: 128px; float: right;" />';
const expectedResult = '<img title="http://src" src="http://src" alt="alternative" style="height: 128px; width: 128px; float: right;"/>';
const result = customEntityTransform(entity);

expect(result).toBe(expectedResult);
Expand Down

0 comments on commit 9c8e34e

Please sign in to comment.