Skip to content

Commit

Permalink
Merge pull request #1324 from axonivy-market/feature/IVYPORTAL-18073-…
Browse files Browse the repository at this point in the history
…Create-file-preview-for-PDF-.log-and-PNG-master

feature/IVYPORTAL-18073-Create-file-preview-for-PDF-.log-and-PNG-master
  • Loading branch information
chnam-axonivy authored Dec 20, 2024
2 parents 93773b5 + 5f0a0c5 commit 65833a5
Show file tree
Hide file tree
Showing 19 changed files with 123 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -361,4 +361,8 @@ function createBlackThinOutline($element) {

function createBlackMediumOutline($element) {
$element.addClass("black-medium-outline");
}

function highlightCasePreviewDocument(){
createRedMediumOutline($("a[id$=':preview-file']"));
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ public enum Variable {
GLOBAL_FOOTER_INFO("Portal.GlobalFooterInfo"), USER_MENU("Portal.UserMenu"), DEFAULT_THEME_MODE("Portal.Theme.Mode"),
GLOBAL_SEARCH_SCOPE_BY_CATEGORIES("Portal.GlobalSearchScopeCategories"),
SHOW_QUICK_GLOBAL_SEARCH("Portal.ShowQuickGlobalSearch"),
ENABLE_SWITCH_THEME_BUTTON("Portal.Theme.EnableSwitchThemeModeButton"), DASHBOARD_MAIN_MENU_ENTRY("Portal.Dashboard.MainMenuEntry"), APPLICATION_NAME("Portal.ApplicationName");
ENABLE_SWITCH_THEME_BUTTON("Portal.Theme.EnableSwitchThemeModeButton"),
DASHBOARD_MAIN_MENU_ENTRY("Portal.Dashboard.MainMenuEntry"),
APPLICATION_NAME("Portal.ApplicationName"),
ENABLE_DOCUMENT_PREVIEW("Portal.Document.EnablePreview");

private String key;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,4 +226,19 @@ public void screenshotProcessOverviewLink() throws IOException {
ScreenshotUtils
.captureHalfLeftPageScreenShot(ScreenshotUtils.PROCESSES_INFORMATION_WIDGET_FOLDER + "process-overview-link");
}

@Test
public void screenshotPreviewDocument() throws IOException{
updateGlobalVariable(Variable.ENABLE_DOCUMENT_PREVIEW.getKey(), "true");
CaseWidgetNewDashBoardPage caseWidget = mainMenuPage.openCaseList();
ScreenshotUtils.resizeBrowser(new Dimension(1600, SCREENSHOT_WIDTH));
WaitHelper.waitForNavigation(() -> caseWidget.openDetailsCase("Order Pizza"));
CaseDetailsPage detailsPage = new CaseDetailsPage();
detailsPage.uploadDocumentWithoutError(FileHelper.getAbsolutePathToTestFile("test-no-files-no-js.pdf"));
refreshPage();
detailsPage.waitForCaseDetailsDisplay();
ScreenshotUtils.executeDecorateJs("highlightCasePreviewDocument()");
ScreenshotUtils.captureElementWithMarginOptionScreenshot(detailsPage.getDocumentBox(),
ScreenshotUtils.CASE_DETAIL_FOLDER + "how-to-preview-document", new ScreenshotMargin(10));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1034,5 +1034,9 @@ public void clickShowCaseOwners() {
public int countCaseOwners() {
return $$("div[id$=':security-member-container']").size();
}

public boolean getFirstItemPreviewDocumentVisible() {
return $("a[id$=':0:preview-file']").exists();
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ public void setup() {

@Test
public void uploadNormalDocument() {
updateGlobalVariable(Variable.ENABLE_DOCUMENT_PREVIEW.getKey(), "true");
initNewDashboardPage(TestAccount.ADMIN_USER);
casePage = menuPage.openCaseList();
caseDetailsPage = casePage.openDetailsCase("Leave Request");
int numberOfDocument = caseDetailsPage.countNumberOfDocument();
caseDetailsPage.uploadDocumentWithoutError(FileHelper.getAbsolutePathToTestFile("test-no-files-no-js.pdf"));
caseDetailsPage.checkNumberOfDocument(numberOfDocument + 1);
assertTrue(caseDetailsPage.getFirstItemPreviewDocumentVisible());
}

@Test
Expand Down Expand Up @@ -84,6 +86,7 @@ public void uploadUnsupportedFileType() {

@Test
public void uploadDocumentAndCheckDocumentName() {
updateGlobalVariable(Variable.ENABLE_DOCUMENT_PREVIEW.getKey(), "true");
final String pdfFile = "test-no-files-no-js.pdf";
final String wordFile = "test-ms-word-extension.doc";
final String unsupportFile = "unsupportedExtension.abc";
Expand All @@ -94,16 +97,22 @@ public void uploadDocumentAndCheckDocumentName() {
caseDetailsPage = casePage.openDetailsCase("Leave Request");
caseDetailsPage.uploadDocumentWithoutError(FileHelper.getAbsolutePathToTestFile(pdfFile));
isCorrectIconExtension(pdfFile, "si si-office-file-pdf-1");
// can preview this document
assertTrue(caseDetailsPage.getFirstItemPreviewDocumentVisible());

casePage = menuPage.openCaseList();
caseDetailsPage = casePage.openDetailsCase("Leave Request");
caseDetailsPage.uploadDocumentWithoutError(FileHelper.getAbsolutePathToTestFile(wordFile));
isCorrectIconExtension(wordFile, "si si-office-file-doc-1");
// can not preview
assertFalse(caseDetailsPage.getFirstItemPreviewDocumentVisible());

casePage = menuPage.openCaseList();
caseDetailsPage = casePage.openDetailsCase("Leave Request");
caseDetailsPage.uploadDocumentWithoutError(FileHelper.getAbsolutePathToTestFile(unsupportFile));
isCorrectIconExtension(unsupportFile, "si si-common-file-empty");
// can not preview
assertFalse(caseDetailsPage.getFirstItemPreviewDocumentVisible());
}

private boolean isCorrectIconExtension(String fileName, String iconClass) {
Expand Down
2 changes: 2 additions & 0 deletions AxonIvyPortal/portal/cms/cms_de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ ch.ivy.addon.portalkit.ui.jsf:
ApplicationName: Der Standard-Anwendungsname, der im Seitentitel angezeigt wird.
BaseQRCodeUrl: Legen Sie die Basis-URL für den anzuzeigenden QR-Code fest.
DefaultThemeMode: Der Standardthemenmodus der Anwendung
EnableDocumentPreview: 'Auf "true" setzen, um die Vorschau von Dokumenten für bestimmte Dateitypen zu aktivieren. Unterstützte Dateitypen sind: pdf, png, jpeg, jpg, txt, log.'
EnableSwitchThemeModeButton: Setzen Sie diesen Wert auf true, um die Schaltfläche "Thema wechseln" zu aktivieren.
GlobalSearchScopeCategoriesNote: Festlegung der Typen, nach denen bei der globalen Suche gesucht werden soll
GooglePlayURL: Legen Sie die URL fest, um die Axon Ivy-Mobilanwendung auf Google Play herunterzuladen.
Expand Down Expand Up @@ -878,6 +879,7 @@ ch.ivy.addon.portalkit.ui.jsf:
yourProcesses: Ihre Prozesse
yourTasks: Ihre Aufgaben
documentFiles:
PreviewDocument: Vorschau
deleteDocumentNote: '{0} hat folgendes gelöscht: {1}'
deleteSuceed: Datei wurde erfolgreich gelöscht
download: Herunterladen
Expand Down
2 changes: 2 additions & 0 deletions AxonIvyPortal/portal/cms/cms_en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ ch.ivy.addon.portalkit.ui.jsf:
ApplicationName: The default application name that will be displayed on the page title.
BaseQRCodeUrl: Set Base URL for QR code to display.
DefaultThemeMode: The default theme mode of the application
EnableDocumentPreview: 'Set to true to enable document preview for some certain file types. Supported file types are: pdf, png, txt, log.'
EnableSwitchThemeModeButton: Set to true to enable the switch theme button.
GlobalSearchScopeCategoriesNote: Defining the types that the global search will search for
GooglePlayURL: Set URL to download Axon Ivy mobile app on Google Play.
Expand Down Expand Up @@ -880,6 +881,7 @@ ch.ivy.addon.portalkit.ui.jsf:
yourProcesses: Your Processes
yourTasks: Your Tasks
documentFiles:
PreviewDocument: Preview
deleteDocumentNote: '{0} has deleted {1}'
deleteSuceed: File deleted successfully
download: Download
Expand Down
2 changes: 2 additions & 0 deletions AxonIvyPortal/portal/cms/cms_es.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ ch.ivy.addon.portalkit.ui.jsf:
ApplicationName: El nombre por defecto de la aplicación que se mostrará en el título de la página.
BaseQRCodeUrl: Establezca la URL base para mostrar el código QR.
DefaultThemeMode: El modo de tema por defecto de la aplicación
EnableDocumentPreview: 'Establecer en "true" para habilitar la vista previa de documentos para ciertos tipos de archivos. Los tipos de archivos compatibles son: pdf, png, jpeg, jpg, txt, log.'
EnableSwitchThemeModeButton: Establecer en true para habilitar el botón de cambio de tema.
GlobalSearchScopeCategoriesNote: Definición de los tipos que buscará la búsqueda global
GooglePlayURL: Establece la URL para descargar la aplicación móvil Axon Ivy en Google Play.
Expand Down Expand Up @@ -877,6 +878,7 @@ ch.ivy.addon.portalkit.ui.jsf:
yourProcesses: Sus procesos
yourTasks: Sus tareas
documentFiles:
PreviewDocument: Vista previa
deleteDocumentNote: '{0} ha eliminado {1}'
deleteSuceed: Archivo eliminado con éxito
download: Descargar
Expand Down
2 changes: 2 additions & 0 deletions AxonIvyPortal/portal/cms/cms_fr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ ch.ivy.addon.portalkit.ui.jsf:
ApplicationName: Le nom de l'application par défaut qui sera affiché dans le titre de la page.
BaseQRCodeUrl: Définir l'URL de base du code QR à afficher.
DefaultThemeMode: Le mode de thème par défaut de l'application
EnableDocumentPreview: 'Définir sur "true" pour activer l''aperçu des documents pour certains types de fichiers. Les types de fichiers pris en charge sont : pdf, png, jpeg, jpg, txt, log.'
EnableSwitchThemeModeButton: Défini à true pour activer le bouton de changement de thème.
GlobalSearchScopeCategoriesNote: Définition des types recherchés par la recherche globale
GooglePlayURL: Définir l'URL pour télécharger l'application mobile Axon Ivy sur Google Play.
Expand Down Expand Up @@ -875,6 +876,7 @@ ch.ivy.addon.portalkit.ui.jsf:
yourProcesses: Vos processus
yourTasks: Vos tâches
documentFiles:
PreviewDocument: Aperçu
deleteDocumentNote: '{0} a supprimé(e) {1}'
deleteSuceed: Le fichier a été supprimé avec succès
download: Télécharger
Expand Down
3 changes: 3 additions & 0 deletions AxonIvyPortal/portal/config/variables.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ Variables:
# If just allow some extensions, list out extensions here, separated by comma. Example: pdf, txt, doc, docx.
WhitelistExtension: doc, docx, xls, xlsx, xlsm, csv, pdf, ppt, pptx, txt, zip, jpg, jpeg, bmp, png

# Set to true to enable document preview for some certain file types. Supported file types are: pdf, png, txt, log.
EnablePreview: false

DateTimeFormat:
# Set to true to hide hours and minutes next to date in the datetime format.
# This setting affects in Tasks, Cases and Statistic results.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@

import javax.faces.bean.ManagedBean;

import org.apache.commons.lang3.StringUtils;
import org.primefaces.model.SortMeta;

import com.axonivy.portal.components.ivydata.bo.IvyDocument;

import ch.ivy.addon.portal.generic.navigation.PortalNavigator;
import ch.ivy.addon.portalkit.enums.GlobalVariable;
import ch.ivy.addon.portalkit.service.GlobalSettingService;
Expand Down Expand Up @@ -80,4 +83,13 @@ public String getCaseDocumentsLink(ICase iCase) {
public SortMeta getDocumentSortByCreationTimestamp() {
return SortFieldUtil.buildSortMeta("creation.timestamp", true);
}

public boolean canPreviewDocument(IvyDocument document) {
boolean enablePreviewSetting = GlobalSettingService.getInstance().findBooleanGlobalSettingValue(GlobalVariable.ENABLE_DOCUMENT_PREVIEW);
if (document != null && StringUtils.startsWithIgnoreCase(document.getContentType(), "image/")) {
return enablePreviewSetting;
}
boolean isSupportedPreviewType = document != null && StringUtils.endsWithAny(document.getPath().toLowerCase(), ".pdf", ".txt", ".log");
return enablePreviewSetting && isSupportedPreviewType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ public enum GlobalVariable {
"appleStoreURL"), GOOGLE_PLAY_URL("Portal.UserMenu.GooglePlayURL", GlobalVariableType.TEXT,
"googlePlayURL"),
APPLICATION_NAME("Portal.ApplicationName", GlobalVariableType.TEXT, "Axon Ivy", "ApplicationName"), HIDE_CASE_CREATOR(
"Portal.Cases.HideCaseCreator", GlobalVariableType.SELECTION, Option.FALSE.toString(), "hideCaseCreator");
"Portal.Cases.HideCaseCreator", GlobalVariableType.SELECTION, Option.FALSE.toString(), "hideCaseCreator"),
ENABLE_DOCUMENT_PREVIEW("Portal.Document.EnablePreview", GlobalVariableType.SELECTION, Option.TRUE.toString(), "enableDocumentPreview");



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
styleClass="u-truncate-text ui-sm-12" width="65%"
filterBy="#{document.name}" filterMatchMode="contains">
<h:panelGroup layout="block" rendered="#{document ne null}" styleClass="task-document-name">
<p:commandLink ajax="false" id="download" styleClass="download-command task-document-name-text u-truncate-text" ariaLabel="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/documentFiles/download')}">
<p:commandLink ajax="false" id="download" styleClass="task-document-name-text u-truncate-text" ariaLabel="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/documentFiles/download')}">
<p:fileDownload value="#{logic.downloadDocument(document)}"/>
<ic:ch.ivy.addon.portalkit.component.document.DocumentNameWithIcon fileName="#{document.name}"
fileSize="#{masterDataBean.getReadableFileSize(document.size)}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,22 @@
styleClass="u-truncate-text document-name">
<h:panelGroup layout="block" rendered="#{document ne null}" styleClass="case-document-name">
<p:commandLink ajax="false" id="download" ariaLabel="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/documentFiles/download')}"
styleClass="download-command case-document-name-text u-truncate-text">
styleClass="case-document-name-text u-truncate-text">
<p:fileDownload value="#{logic.downloadDocument(document)}" />
<ic:ch.ivy.addon.portalkit.component.document.DocumentNameWithIcon fileName="#{document.name}" fileSize="#{masterDataBean.getReadableFileSize(document.size)}"
symbolStyleClass="case-details-document-download-icon"
fileNameStyleClass="js-document-name document-name"
fileSizeStyleClass="document-size" />
</p:commandLink>
<p:commandLink id="preview-file" ariaLabel="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/documentFiles/PreviewDocument')}"
styleClass="si si-view-1 Fright document-preview ui-sm-hidden"
actionListener="#{logic.downloadDocument(document)}"
rendered="#{caseTaskDocumentBean.canPreviewDocument(document)}"
update="#{cc.clientId}:preview-document-dialog"
oncomplete="PF('preview-document-dialog').show()">
<p:tooltip for="preview-file" trackMouse="true" hideEvent="mouseleave click"
value="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/documentFiles/PreviewDocument')}" />
</p:commandLink>
<p:commandLink id="delete-file" actionListener="#{data.setDocument(document)}"
ariaLabel="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/caseDetails/deleteFile')} #{document.name}"
rendered="#{caseTaskDocumentBean.canWriteDocument(case)}"
Expand Down Expand Up @@ -157,6 +166,16 @@
update="#{cc.clientId}:document-upload-form:upload-messages @this" />
</div>
</p:dialog>

<p:dialog widgetVar="preview-document-dialog" id="preview-document-dialog" appendTo="@(body)"
header="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/documentFiles/PreviewDocument')}"
modal="true" resizable="false" width="650" height="630" showEffect="fade" hideEffect="fade"
styleClass="case-upload-dialog" dynamic="true" fitViewport="true" responsive="true">
<div class="ui-g-12">
<p:media value="#{data.streamedContent}" width="100%" height="600" cache="false" id="media-content" player="pdf" rendered="#{!data.isImage}"/>
<p:graphicImage value="#{data.streamedContent}" stream="false" height="600" width="100%" rendered="#{data.isImage}" styleClass="document-preview-image"/>
</div>
</p:dialog>

<ui:decorate template="/layouts/decorator/portal-dialog-with-icon.xhtml">
<ui:param name="widgetVar" value="document-deletion-dialog" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,9 @@
"name" : "deleteDocumentMessage",
"type" : "String",
"modifiers" : [ "PERSISTENT" ]
}, {
"name" : "isImage",
"type" : "Boolean",
"modifiers" : [ "PERSISTENT" ]
} ]
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,11 @@
],
"map" : {
"out.document" : "param.document"
}
},
"code" : [
"import org.apache.commons.lang3.StringUtils;",
"out.isImage = param.document!= null && StringUtils.startsWithIgnoreCase(param.document.getContentType(), \"image/\");"
]
},
"result" : {
"params" : [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,22 @@
sortBy="#{document.name}"
styleClass="">
<h:panelGroup layout="block" rendered="#{document ne null}" styleClass="task-document-name">
<p:commandLink ajax="false" id="download" styleClass="download-command task-document-name-text u-truncate-text" ariaLabel="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/documentFiles/download')}">
<p:commandLink ajax="false" id="download" styleClass="task-document-name-text u-truncate-text" ariaLabel="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/documentFiles/download')}">
<p:fileDownload value="#{logic.downloadDocument(document)}" />
<ic:ch.ivy.addon.portalkit.component.document.DocumentNameWithIcon fileName="#{document.name}" fileSize="#{masterDataBean.getReadableFileSize(document.size)}"
symbolStyleClass="task-details-document-download-icon"
fileNameStyleClass="document-name"
fileSizeStyleClass="document-size" />
</p:commandLink>
<p:commandLink id="preview-file" ariaLabel="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/documentFiles/PreviewDocument')}"
styleClass="si si-view-1 Fright document-preview ui-sm-hidden"
actionListener="#{logic.downloadDocument(document)}"
rendered="#{caseTaskDocumentBean.canPreviewDocument(document)}"
update="#{cc.clientId}:preview-document-dialog"
oncomplete="PF('preview-document-dialog').show()">
<p:tooltip for="preview-file" trackMouse="true" hideEvent="mouseleave click"
value="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/documentFiles/PreviewDocument')}" />
</p:commandLink>
<p:commandLink id="delete-file" actionListener="#{data.setDocument(document)}" ariaLabel="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/taskDetails/deleteFile')} #{document.name}"
rendered="#{caseTaskDocumentBean.canWriteDocument(task)}"
styleClass="si si-remove Fright task-document-download" oncomplete="PF('document-deletion-dialog').show()">
Expand Down Expand Up @@ -155,7 +164,16 @@
update="#{p:resolveFirstComponentWithId('upload-messages', view).clientId} @this" />
</div>
</p:dialog>


<p:dialog widgetVar="preview-document-dialog" id="preview-document-dialog" appendTo="@(body)"
header="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/documentFiles/PreviewDocument')}"
modal="true" resizable="false" width="650" height="630" showEffect="fade" hideEffect="fade"
styleClass="case-upload-dialog" dynamic="true" fitViewport="true" responsive="true">
<div class="ui-g-12">
<p:media value="#{data.streamedContent}" width="100%" height="600" cache="false" id="media-content" player="pdf" rendered="#{!data.isImage}"/>
<p:graphicImage value="#{data.streamedContent}" stream="false" height="600" width="100%" rendered="#{data.isImage}" styleClass="document-preview-image"/>
</div>
</p:dialog>
<ui:decorate template="/layouts/decorator/portal-dialog-with-icon.xhtml">
<ui:param name="id" value="document-deletion-dialog" />
<ui:param name="widgetVar" value="document-deletion-dialog" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,9 @@
"name" : "deleteDocumentMessage",
"type" : "String",
"modifiers" : [ "PERSISTENT" ]
}, {
"name" : "isImage",
"type" : "Boolean",
"modifiers" : [ "PERSISTENT" ]
} ]
}
8 changes: 8 additions & 0 deletions AxonIvyPortal/portal/webContent/resources/css/module.css
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,14 @@ span.case-details-document-add-link, span.task-details-document-add-link {
top: 2px;
right: 4px;
}
.document-preview{
position:absolute;
top:2px;
right:30px;
}
.document-preview-image{
object-fit:contain;
}
/********************************** CASE ITEM SIMILAR TO TASK ITEM CLASSES **********************************/
.case-widget-container .case-widget-top-header {
position: relative;
Expand Down

0 comments on commit 65833a5

Please sign in to comment.