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

feature/IVYPORTAL-18073-Create-file-preview-for-PDF-.log-and-PNG-master #1324

Merged
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 @@ -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
Loading