Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import io.jmix.messagetemplatesflowui.kit.component.GrapesJsBlock;
import io.jmix.messagetemplatesflowui.view.htmleditor.HtmlEditorView;
import io.jmix.messagetemplatesflowui.view.messagetemplateparameter.MessageTemplateParameterDetailView;
import io.jmix.messagetemplatesflowui.view.messagetemplatepreview.MessageTemplatesPreviewer;
import org.springframework.beans.factory.annotation.Autowired;

import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -79,6 +80,8 @@ public class MessageTemplateDetailView extends StandardDetailView<MessageTemplat
protected Metadata metadata;
@Autowired
protected AccessManager accessManager;
@Autowired
protected MessageTemplatesPreviewer messageTemplatesPreviewer;

@Autowired
protected UiProperties uiProperties;
Expand Down Expand Up @@ -237,4 +240,9 @@ public void parametersDataGridCreateViewConfigurer(MessageTemplateParameterDetai
public void parametersDataGridEditViewConfigurer(MessageTemplateParameterDetailView detailView) {
detailView.setParentTemplateParameters(getEditedEntity().getParameters());
}

@Subscribe("previewButton")
public void onPreviewButtonClick(ClickEvent<JmixButton> event) {
messageTemplatesPreviewer.showPreview(getEditedEntity(), this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import io.jmix.messagetemplates.entity.MessageTemplateParameter;
import io.jmix.messagetemplates.entity.TemplateType;
import io.jmix.messagetemplatesflowui.accesscontext.UiImportExportMessageTemplateContext;
import io.jmix.messagetemplatesflowui.view.messagetemplatepreview.MessageTemplatesPreviewer;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -101,6 +102,8 @@ public class MessageTemplateListView extends StandardListView<MessageTemplate> {
protected Downloader downloader;
@Autowired
protected Notifications notifications;
@Autowired
protected MessageTemplatesPreviewer messageTemplatesPreviewer;

protected boolean isCreatePermitted;
protected boolean isImportExportPermitted;
Expand Down Expand Up @@ -146,6 +149,12 @@ public void onMessageTemplatesDataGridCopy(ActionPerformedEvent event) {
}
}

@Subscribe("messageTemplatesDataGrid.preview")
public void onMessageTemplatesDataGridPreview(ActionPerformedEvent event) {
MessageTemplate selectedItem = messageTemplatesDataGrid.getSingleSelectedItem();
messageTemplatesPreviewer.showPreview(selectedItem, this);
}

@Subscribe("importField")
public void onImportFileUploadSucceeded(FileUploadSucceededEvent<FileUploadField, byte[]> event) {
byte[] fileBytes = event.getSource().getValue();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright 2026 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.jmix.messagetemplatesflowui.view.messagetemplatepreview;

import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Html;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import io.jmix.flowui.UiComponents;
import io.jmix.flowui.component.textarea.JmixTextArea;
import io.jmix.flowui.download.DownloadFormat;
import io.jmix.flowui.download.Downloader;
import io.jmix.flowui.kit.component.button.JmixButton;
import io.jmix.flowui.view.*;
import io.jmix.messagetemplates.entity.TemplateType;
import org.springframework.beans.factory.annotation.Autowired;

import java.nio.charset.StandardCharsets;

@ViewController("msgtmp_MessageTemplatePreviewView")
@ViewDescriptor("message-template-preview-view.xml")
@DialogMode(resizable = true)
public class MessageTemplatePreviewView extends StandardView {

@Autowired
protected UiComponents uiComponents;
@Autowired
protected Downloader downloader;

@ViewComponent
protected VerticalLayout contentBox;
@ViewComponent
protected JmixButton openInNewTabButton;

protected TemplateType type;
protected String content;

@Subscribe
public void onInit(InitEvent event) {
downloader.setShowNewWindow(true);
}

public void setPreviewContent(TemplateType type, String content) {
this.type = type;
this.content = content;
}

@Subscribe
public void onBeforeShow(BeforeShowEvent event) {
if (TemplateType.HTML.equals(type)) {
initHtmlLayout();
} else {
initTextLayout();
}
}

protected void initHtmlLayout() {
openInNewTabButton.setVisible(true);

// <div> wrapping required to avoid 'HTML must contain exactly one top-level element' exception
Html html = new Html("<div>%s</div>".formatted(content));
contentBox.addAndExpand(html);
}

protected void initTextLayout() {
JmixTextArea textArea = uiComponents.create(JmixTextArea.class);

textArea.setReadOnly(true);
textArea.setWidth("60em");
textArea.setValue(content);
contentBox.addAndExpand(textArea);
}

@Subscribe("openInNewTabButton")
public void onOpenInNewTabButtonClick(ClickEvent<JmixButton> event) {
downloader.download(content.getBytes(StandardCharsets.UTF_8), "preview.html", DownloadFormat.HTML);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright 2026 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.jmix.messagetemplatesflowui.view.messagetemplatepreview;

import io.jmix.core.annotation.Internal;
import io.jmix.flowui.DialogWindows;
import io.jmix.flowui.view.StandardOutcome;
import io.jmix.flowui.view.View;
import io.jmix.messagetemplates.MessageTemplatesGenerator;
import io.jmix.messagetemplates.entity.MessageTemplate;
import io.jmix.messagetemplatesflowui.view.parametersinputdialog.MessageTemplateParametersInputDialog;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.Map;

/**
* Provides functionality for previewing {@link MessageTemplate}.
* <p>
* Allows users to enter parameters used for generating a message preview
* and displays the result in a dialog.
* <p>
* This is an internal component and is not intended for direct use in application code.
*/
@Internal
@Component("msgtmp_MessageTemplatesPreviewer")
public class MessageTemplatesPreviewer {

@Autowired
protected MessageTemplatesGenerator messageTemplatesGenerator;
@Autowired
protected DialogWindows dialogWindows;

/**
* Opens a preview for the specified message template.
* <p>
* If the template contains parameters, a dialog for parameter input is shown first.
* After confirmation, the template is generated and the result is displayed.
*
* @param messageTemplate the message template (can be {@code null})
* @param origin the originating view used to open dialogs
*/
public void showPreview(@Nullable MessageTemplate messageTemplate, View<?> origin) {
if (messageTemplate == null) {
return;
}

if (!messageTemplate.getParameters().isEmpty()) {
dialogWindows.view(origin, MessageTemplateParametersInputDialog.class)
.withViewConfigurer(view ->
view.setTemplateParameters(messageTemplate.getParameters()))
.withAfterCloseListener(event -> {
if (event.closedWith(StandardOutcome.SAVE)) {
showTemplate(messageTemplate, event.getView().getParameters(), origin);
}
})
.open();
} else {
showTemplate(messageTemplate, Collections.emptyMap(), origin);
}
}

/**
* Generates the message template using the provided parameters
* and displays the result in the preview dialog.
*
* @param template the message template
* @param parameters parameters used for generation
* @param origin the originating view
*/
protected void showTemplate(MessageTemplate template, Map<String, Object> parameters, View<?> origin) {
String content = messageTemplatesGenerator.generateMessage(template, parameters);

dialogWindows.view(origin, MessageTemplatePreviewView.class)
.withViewConfigurer(view -> view.setPreviewContent(template.getType(), content))
.open();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ io.jmix.messagetemplatesflowui.view.messagetemplategroup/MessageTemplateGroupDet
io.jmix.messagetemplatesflowui.view.messagetemplateblock/MessageTemplateBlockListView.title=Template blocks
io.jmix.messagetemplatesflowui.view.messagetemplateblock/MessageTemplateBlockDetailView.title=Template block
io.jmix.messagetemplatesflowui.view.messagetemplateparameter/MessageTemplateParameterDetailView.title=Template parameter
io.jmix.messagetemplatesflowui.view.messagetemplatepreview/MessageTemplatePreviewView.title=Preview
io.jmix.messagetemplatesflowui.view.parametersinputdialog/MessageTemplateParametersInputDialog.title=Input parameters

io.jmix.messagetemplatesflowui.view.messagetemplate/exportButton.text=Export
io.jmix.messagetemplatesflowui.view.messagetemplate/messageTemplatesDataGrid.copyAction.text=Copy
io.jmix.messagetemplatesflowui.view.messagetemplate/messageTemplatesDataGrid.previewAction.text=Preview
io.jmix.messagetemplatesflowui.view.messagetemplate/messageTemplatesDataGrid.exportJsonAction.text=Export as JSON
io.jmix.messagetemplatesflowui.view.messagetemplate/messageTemplatesDataGrid.exportZipAction.text=Export as ZIP
io.jmix.messagetemplatesflowui.view.messagetemplate/importField.uploadText=Import
Expand All @@ -39,6 +41,7 @@ io.jmix.messagetemplatesflowui.view.messagetemplate/mainTabSheet.parametersTab.l
io.jmix.messagetemplatesflowui.view.messagetemplate/importTemplateField.title=Import HTML
io.jmix.messagetemplatesflowui.view.messagetemplate/editCodeBtn.title=Edit HTML
io.jmix.messagetemplatesflowui.view.messagetemplate/viewBtn.title=View HTML
io.jmix.messagetemplatesflowui.view.messagetemplate/previewButton.text=Preview
io.jmix.messagetemplatesflowui.view.messagetemplate/plainTextArea.header=Template content
io.jmix.messagetemplatesflowui.view.messagetemplate/emptyContentValidationMessage=Template content must not be blank

Expand All @@ -49,6 +52,8 @@ io.jmix.messagetemplatesflowui.view.messagetemplateparameter/mainTabSheet.detail
io.jmix.messagetemplatesflowui.view.messagetemplateparameter/mainTabSheet.localizationTab.label=Localization
io.jmix.messagetemplatesflowui.view.messagetemplateparameter/uniqueAliasValidationMessage=A parameter with the same alias already exist

io.jmix.messagetemplatesflowui.view.messagetemplatepreview/openInNewTabButton.text=Open in new tab

io.jmix.messagetemplatesflowui.view.messagetemplateparameter.model/MessageTemplateParameterLocalization=Message template parameter localization
io.jmix.messagetemplatesflowui.view.messagetemplateparameter.model/MessageTemplateParameterLocalization.id=ID
io.jmix.messagetemplatesflowui.view.messagetemplateparameter.model/MessageTemplateParameterLocalization.locale=Locale
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@
<hbox id="htmlTemplateControlsPanel" classNames="buttons-panel">
<fileUploadField id="importTemplateField" uploadIcon="UPLOAD"
acceptedFileTypes=".html"/>
<button id="viewBtn" icon="DOWNLOAD" title="msg://viewBtn.title"/>
<button id="editCodeBtn" icon="CODE" title="msg://editCodeBtn.title"/>
<button id="viewBtn" icon="EYE" title="msg://viewBtn.title"/>
</hbox>
<msgtmp:grapesJs id="grapesJsEditor" width="100%"
minHeight="20em">
Expand Down Expand Up @@ -132,6 +132,8 @@
</tabSheet>
<hbox id="detailActions">
<button id="saveAndCloseButton" action="saveAction"/>
<button id="previewButton" icon="EYE"
text="msg://previewButton.text"/>
<button id="closeButton" action="closeAction"/>
</hbox>
</layout>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
<button id="editButton" action="messageTemplatesDataGrid.edit"/>
<button id="removeButton" action="messageTemplatesDataGrid.remove"/>
<button id="copyButton" action="messageTemplatesDataGrid.copy"/>
<button id="previewButton" action="messageTemplatesDataGrid.preview"/>
<dropdownButton id="exportButton" text="msg://exportButton.text" icon="DOWNLOAD">
<items>
<actionItem id="exportJsonAction" ref="messageTemplatesDataGrid.exportJson"/>
Expand All @@ -79,6 +80,8 @@
<action id="remove" type="list_remove"/>
<action id="copy" type="list_itemTracking" icon="COPY"
text="msg://messageTemplatesDataGrid.copyAction.text"/>
<action id="preview" type="list_itemTracking" icon="EYE"
text="msg://messageTemplatesDataGrid.previewAction.text"/>
<action id="exportJson" icon="FILE_CODE"
text="msg://messageTemplatesDataGrid.exportJsonAction.text"/>
<action id="exportZip" icon="FILE_ZIP"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
~ Copyright 2026 Haulmont.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<view xmlns="http://jmix.io/schema/flowui/view"
title="msg://MessageTemplatePreviewView.title">
<actions>
<action id="closeAction" type="view_close"/>
</actions>
<layout alignItems="STRETCH"
padding="false" spacing="false"
expand="contentBox">
<vbox id="contentBox"/>
<hbox id="actionsPanel"
classNames="footer-panel">
<button id="openInNewTabButton" icon="EXTERNAL_LINK" text="msg://openInNewTabButton.text" visible="false"/>
<button id="closeButton" action="closeAction"/>
</hbox>
</layout>
</view>
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ io.jmix.messagetemplatesflowui.view.messagetemplategroup/MessageTemplateGroupDet
io.jmix.messagetemplatesflowui.view.messagetemplateblock/MessageTemplateBlockListView.title=Template blocks
io.jmix.messagetemplatesflowui.view.messagetemplateblock/MessageTemplateBlockDetailView.title=Template block
io.jmix.messagetemplatesflowui.view.messagetemplateparameter/MessageTemplateParameterDetailView.title=Template parameter
io.jmix.messagetemplatesflowui.view.messagetemplatepreview/MessageTemplatePreviewView.title=Preview
io.jmix.messagetemplatesflowui.view.parametersinputdialog/MessageTemplateParametersInputDialog.title=Input parameters

io.jmix.messagetemplatesflowui.view.messagetemplate/exportButton.text=Export
io.jmix.messagetemplatesflowui.view.messagetemplate/messageTemplatesDataGrid.copyAction.text=Copy
io.jmix.messagetemplatesflowui.view.messagetemplate/messageTemplatesDataGrid.previewAction.text=Preview
io.jmix.messagetemplatesflowui.view.messagetemplate/messageTemplatesDataGrid.exportJsonAction.text=Export as JSON
io.jmix.messagetemplatesflowui.view.messagetemplate/messageTemplatesDataGrid.exportZipAction.text=Export as ZIP
io.jmix.messagetemplatesflowui.view.messagetemplate/importField.uploadText=Import
Expand All @@ -39,6 +41,7 @@ io.jmix.messagetemplatesflowui.view.messagetemplate/mainTabSheet.parametersTab.l
io.jmix.messagetemplatesflowui.view.messagetemplate/importTemplateField.title=Import HTML
io.jmix.messagetemplatesflowui.view.messagetemplate/editCodeBtn.title=Edit HTML
io.jmix.messagetemplatesflowui.view.messagetemplate/viewBtn.title=View HTML
io.jmix.messagetemplatesflowui.view.messagetemplate/previewButton.text=Preview
io.jmix.messagetemplatesflowui.view.messagetemplate/plainTextArea.header=Template content
io.jmix.messagetemplatesflowui.view.messagetemplate/emptyContentValidationMessage=Template content must not be blank

Expand All @@ -49,6 +52,8 @@ io.jmix.messagetemplatesflowui.view.messagetemplateparameter/mainTabSheet.detail
io.jmix.messagetemplatesflowui.view.messagetemplateparameter/mainTabSheet.localizationTab.label=Localization
io.jmix.messagetemplatesflowui.view.messagetemplateparameter/uniqueAliasValidationMessage=A parameter with the same alias already exist

io.jmix.messagetemplatesflowui.view.messagetemplatepreview/openInNewTabButton.text=Open in new tab

io.jmix.messagetemplatesflowui.view.messagetemplateparameter.model/MessageTemplateParameterLocalization=Message template parameter localization
io.jmix.messagetemplatesflowui.view.messagetemplateparameter.model/MessageTemplateParameterLocalization.id=ID
io.jmix.messagetemplatesflowui.view.messagetemplateparameter.model/MessageTemplateParameterLocalization.locale=Locale
Expand Down
Loading