package org.gcube.portlets.user.workspace.client.view.windows; import java.util.Date; import java.util.List; import java.util.Map; import org.gcube.portlets.user.workspace.client.AppControllerExplorer; import org.gcube.portlets.user.workspace.client.ConstantsExplorer; import org.gcube.portlets.user.workspace.client.event.CreateSharedFolderEvent; import org.gcube.portlets.user.workspace.client.event.FileDownloadEvent; import org.gcube.portlets.user.workspace.client.event.FileDownloadEvent.DownloadType; import org.gcube.portlets.user.workspace.client.interfaces.GXTFolderItemTypeEnum; import org.gcube.portlets.user.workspace.client.model.FileGridModel; import org.gcube.portlets.user.workspace.client.model.FileModel; import org.gcube.portlets.user.workspace.client.resources.Resources; import org.gcube.portlets.user.workspace.client.workspace.GWTWorkspaceItem; import org.gcube.portlets.user.workspace.client.workspace.folder.item.GWTExternalImage; import org.gcube.portlets.user.workspace.client.workspace.folder.item.gcube.GWTImageDocument; import org.gcube.portlets.user.workspace.shared.PublicLink; import org.gcube.portlets.widgets.workspacesharingwidget.client.rpc.WorkspaceSharingServiceAsync; import com.github.gwtbootstrap.client.ui.Button; import com.github.gwtbootstrap.client.ui.ControlGroup; import com.github.gwtbootstrap.client.ui.Label; import com.github.gwtbootstrap.client.ui.TextArea; import com.github.gwtbootstrap.client.ui.Tooltip; import com.github.gwtbootstrap.client.ui.constants.ButtonType; import com.github.gwtbootstrap.client.ui.constants.IconType; import com.github.gwtbootstrap.client.ui.constants.LabelType; import com.github.gwtbootstrap.client.ui.constants.ResizeType; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style.Float; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.LoadEvent; import com.google.gwt.event.dom.client.LoadHandler; import com.google.gwt.http.client.URL; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.NumberFormat; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Frame; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.NamedFrame; import com.google.gwt.user.client.ui.Widget; // TODO: Auto-generated Javadoc /** * The Class DialogGetInfoBootstrap. * * @author Francesco Mangiacrapa at ISTI-CNR Pisa (Italy) * Jul 13, 2020 */ public class DialogGetInfoBootstrap extends Composite { private static final int PREVIEW_WAITING_TIME = 9000; //9 sec private static DialogGetInfoBootstrapUiBinder uiBinder = GWT.create(DialogGetInfoBootstrapUiBinder.class); /** * The Interface DialogGetInfoBootstrapUiBinder. * * @author Francesco Mangiacrapa at ISTI-CNR Pisa (Italy) * Jul 13, 2020 */ interface DialogGetInfoBootstrapUiBinder extends UiBinder { } public static final String EMPTY = "empty"; private final NumberFormat number = ConstantsExplorer.numberFormatterKB; /** * Instantiates a new dialog get info bootstrap. */ public DialogGetInfoBootstrap() { initWidget(uiBinder.createAndBindUi(this)); } public static final String NOT_AVAILABLE = "n.a."; private Map gCubeProperties; @UiField HorizontalPanel hpItemType; @UiField HorizontalPanel hpHeaderDetails; @UiField Button buttonClose; @UiField HTMLPanel htmlPanelImagePreview; @UiField HTMLPanel htmlPanelFilePreview; @UiField HTML txtName; @UiField HTML txtId; @UiField HTML txtLocation; @UiField ControlGroup cgTxtIsPublic; @UiField HTML txtIsPublic; @UiField HTML txtMimeType; @UiField ControlGroup cgTxtMimeType; @UiField ControlGroup cgThreddsSynched; @UiField HTML txtThreddsSynched; @UiField ControlGroup cgGcubeProperties; @UiField TextArea txtAreaGcubeProperties; @UiField TextArea txtAreaDescription; @UiField HTML txtOwner; @UiField HTML txtCreated; @UiField HTML txtLastMofication; @UiField HTML txtSize; @UiField HTML txtShared; @UiField Button buttonUpdateDescription; @UiField Button buttonSaveDescription; @UiField Button buttonUpdateGcubeProperties; @UiField Button buttonUpdateShare; @UiField ControlGroup cgSharedWith; @UiField HTML txtSharedWith; private FileModel fileModel; private Command onCloseCommand; private Tooltip tooltipDownload = new Tooltip("Download"); private Button buttonDownload = new Button("Download"); // private Tooltip tooltipSharebleLink = new Tooltip("Get Shareable Link"); // private Button buttonShareableLink = new Button(); private DateTimeFormat dateFormatter = DateTimeFormat.getFormat("dd MMM yyyy, hh:mm aaa"); private boolean iFrameGoogleDocViewerLoaded = false; private Long fileSize = null; private Map> mapAllowedMimeTypesForPreview; private Image spinnerImage = Resources.getIconLoading().createImage(); private Image noPreviewAvailable = new Image(Resources.getPreviewNotAvailable()); private Frame iFrameGDV = null; private Timer timerGDV = null; /** * Instantiates a new dialog get info bootstrap. * * @param fileModel the file model * @param onCloseCommand the on close command * @param mapAllowedMimeTypesForPreview the map allowed mime types for preview */ public DialogGetInfoBootstrap(final FileModel fileModel, final Command onCloseCommand, Map> mapAllowedMimeTypesForPreview) { initWidget(uiBinder.createAndBindUi(this)); this.fileModel = fileModel; this.onCloseCommand = onCloseCommand; this.mapAllowedMimeTypesForPreview = mapAllowedMimeTypesForPreview; this.cgTxtMimeType.setVisible(true); buttonClose.getElement().getStyle().setFloat(Float.RIGHT); hpItemType.add(fileModel.getIcon()); Label labelItemType = new Label(); labelItemType.setType(LabelType.DEFAULT); //labelItemType.getElement().getStyle().setMarginLeft(10, Unit.PX); String label = null; GXTFolderItemTypeEnum typeEnum = fileModel.getGXTFolderItemType(); //in case of folder see #19600 if(fileModel.isDirectory()) { label = "Private Folder"; if(fileModel.isPublic()) { //is public label = "Public Folder"; if(fileModel.isShared()) { label = "Shared and Public Folder"; } }else { //is not public if(fileModel.isShared()) { //is shared label = "Shared Folder"; if(fileModel.isVreFolder()) { label = "VRE Folder"; } } } //hiding the type cgTxtMimeType.setVisible(false); }else { //in case of file see #19600 if (typeEnum != null) { //the file is categorized label = typeEnum.getLabel(); label = label.replace("External ", ""); } else { //the file is NOT categorized using the default "File" label = "File"; } } labelItemType.setText(label); hpItemType.add(labelItemType); buttonDownload.setType(ButtonType.LINK); buttonDownload.setIcon(IconType.CLOUD_DOWNLOAD); tooltipDownload.add(buttonDownload); hpItemType.add(tooltipDownload); // buttonShareableLink.setType(ButtonType.LINK); // buttonShareableLink.setIcon(IconType.LINK); // buttonShareableLink.set // tooltipSharebleLink.add(buttonShareableLink); // hpItemType.add(tooltipSharebleLink); // Setting name htmlSetValue(txtName, fileModel.getName()); htmlSetValue(txtId, fileModel.getIdentifier()); if (fileModel.isRoot()) txtLocation.setHTML("/"); else loadLocation(fileModel); if (fileModel.isDirectory()) { cgTxtIsPublic.setVisible(true); htmlSetValue(txtIsPublic, fileModel.isPublic() + ""); if (fileModel.getSynchedThreddsStatus() != null) { txtThreddsSynched.setVisible(true); htmlSetValue(txtThreddsSynched, fileModel.getSynchedThreddsStatus() + ""); txtThreddsSynched.setHTML(fileModel.getSynchedThreddsStatus() + ""); } } //mimetype htmlSetValue(txtMimeType, fileModel.getType()); txtAreaDescription.setResize(ResizeType.VERTICAL); if (fileModel.isDirectory()) { txtAreaDescription.setValue(fileModel.getDescription()); // add(txtAreaDescription); } else loadDescription(fileModel.getIdentifier()); //owner htmlSetValue(txtOwner, fileModel.getOwnerFullName()); //creation date loadCreationDate(fileModel.getIdentifier()); if(fileModel instanceof FileGridModel) { FileGridModel fileGridModel = ((FileGridModel) fileModel); //last update htmlSetValue(txtLastMofication, dateFormatter.format(fileGridModel.getLastModification())); //size fileSize = fileGridModel.getSize(); htmlSetValue(txtSize, getFormattedSize(fileGridModel.getSize())); }else { loadLastModificationDate(fileModel.getIdentifier()); loadSize(fileModel.getIdentifier()); } htmlSetValue(txtShared, fileModel.isShared()+""); // USERS SHARED if (fileModel.isShared()) { cgSharedWith.setVisible(true); loadACLsDescriptionForSharedFolder(fileModel.getIdentifier()); } boolean previewManaged = false; if (typeEnum != null) { // is it an image? if (typeEnum.equals(GXTFolderItemTypeEnum.IMAGE_DOCUMENT) || typeEnum.equals(GXTFolderItemTypeEnum.EXTERNAL_IMAGE)) { previewManaged = true; loadThumbnailsForImage(); } // is it a GCUBE-Item? if (typeEnum.equals(GXTFolderItemTypeEnum.GCUBE_ITEM)) { previewManaged = true; //preview not avaible for the type GCUBE_ITEM loadGcubeItemProperties(); } } //If the preview is not managed //through the previous code //managing it by checking the mime-type if(!previewManaged) { if (!fileModel.isDirectory() && mapAllowedMimeTypesForPreview.containsKey(fileModel.getType())) { // SOLUTION BASED ON GOOGLE DOC VIEWER GWT.log("Mime type " + fileModel.getType() + " allowed for preview, try to display it"); final HTML loadingPreviewHTML = new HTML(); setPlaceholder(loadingPreviewHTML, true, "loading preview..."); htmlPanelFilePreview.add(loadingPreviewHTML); htmlPanelFilePreview.setVisible(true); AppControllerExplorer.rpcWorkspaceService.getPublicLinkForFileItemId(fileModel.getIdentifier(), false, new AsyncCallback() { @Override public void onFailure(Throwable caught) { removePlaceHolder(loadingPreviewHTML); GWT.log("Error on loading the Public link for: "+fileModel.getIdentifier()); htmlPanelFilePreview.add(noPreviewAvailable); htmlPanelFilePreview.setVisible(true); } @Override public void onSuccess(PublicLink result) { GWT.log("The PublicLink link is: " + result); if (result != null) { // if file size is null or greater than 25MB long byteTo25MB = 1024 * 1024 * 25; GWT.log("The file size is: " + fileSize); if (fileSize == null || fileSize > byteTo25MB) { GWT.log("The file size is null or greater than " + byteTo25MB + ", returning"); // htmlPanelFilePreview.add(new Image(Resources.getPreviewNotAvailable())); return; } String googleDocViewerURL = "https://docs.google.com/viewer?url=" + URL.encode(result.getCompleteURL()) + "&embedded=true"; iFrameGDV = instanceFrame(googleDocViewerURL, loadingPreviewHTML); final long startTime = new Date().getTime(); timerGDV = new Timer() { @Override public void run() { GWT.log("Checking if the iFrameGoogleDocViewer is ready"); if (iFrameGoogleDocViewerLoaded) { removePlaceHolder(loadingPreviewHTML); GWT.log("iFrameGoogleDocViewer currently loaded, cancelling timer"); cancel(); return; } long checkTime = new Date().getTime(); long diff = checkTime - startTime; if (diff > PREVIEW_WAITING_TIME) {// is greater than 10 sec try { GWT.log("iFrameGoogleDocViewer not loaded within "+PREVIEW_WAITING_TIME+" sec, cancelling timer, removing iframe"); cancel(); removePlaceHolder(loadingPreviewHTML); htmlPanelFilePreview.add(noPreviewAvailable); iFrameGDV.setVisible(false); htmlPanelFilePreview.remove(iFrameGDV); } catch (Exception e) { // Silent } } } }; timerGDV.scheduleRepeating(PREVIEW_WAITING_TIME/3); htmlPanelFilePreview.add(iFrameGDV); } } }); } else { GWT.log("Mime type " + fileModel.getType() + " NOT allowed for preview, displaying 'No preview available'"); htmlPanelFilePreview.add(noPreviewAvailable); htmlPanelFilePreview.setVisible(true); } } addHandlers(); } @Override protected void onDetach() { super.onDetach(); GWT.log("Detached..."); htmlPanelFilePreview.clear(); if(timerGDV!=null) { try { timerGDV.cancel(); }catch (Exception e) { // TODO: handle exception } } } public Frame instanceFrame(String fileURL, final HTML thePreviewPlaceholder) { //addLoading(); String urlEncoded = URL.encode(fileURL); GWT.log("Encoded url for instanciating frame is " + urlEncoded); iFrameGoogleDocViewerLoaded = false; final NamedFrame frame = new NamedFrame("iFrameGoogleDocViewer"); frame.setUrl(urlEncoded); frame.setVisible(false); frame.getElement().setId("iFrameGoogleDocViewer"); frame.getElement().getStyle().setBorderWidth(0, Unit.PX); frame.addLoadHandler(new LoadHandler() { @Override public void onLoad(LoadEvent arg0) { GWT.log("iFrameGoogleDocViewer loaded"); iFrameGoogleDocViewerLoaded = true; removePlaceHolder(thePreviewPlaceholder); frame.getElement().addClassName("my-preview-doc"); frame.setVisible(true); } }); return frame; } /** * Adds the handlers. */ private void addHandlers() { buttonClose.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { onCloseCommand.execute(); } }); buttonUpdateDescription.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { txtAreaDescription.setReadOnly(false); txtAreaDescription.setFocus(true); buttonSaveDescription.setVisible(true); } }); buttonSaveDescription.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { buttonSaveDescription.setVisible(false); txtAreaDescription.setReadOnly(true); AppControllerExplorer.rpcWorkspaceService.updateDescriptionForItem(fileModel.getIdentifier(), txtAreaDescription.getValue(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { new MessageBoxAlert("Error on updating description...", caught.getMessage(), null); } @Override public void onSuccess(String result) { GWT.log("Updated the description as: "+result); txtAreaDescription.setValue(result); } }); } }); final Command cmdReloadProperties = new Command() { @Override public void execute() { loadGcubeItemProperties(); } }; buttonUpdateGcubeProperties.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { final DialogEditProperties editProperties = new DialogEditProperties(fileModel, cmdReloadProperties); editProperties.show(); editProperties.setProperties(gCubeProperties); } }); buttonUpdateShare.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { AppControllerExplorer.getEventBus().fireEvent(new CreateSharedFolderEvent(fileModel, fileModel.getParentFileModel(),false)); onCloseCommand.execute(); } }); buttonDownload.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { AppControllerExplorer.getEventBus() .fireEvent(new FileDownloadEvent(fileModel.getIdentifier(), fileModel.getName(), DownloadType.SHOW, fileModel.isDirectory() || fileModel.isVreFolder(), null)); } }); } /** * Html set value. * * @param field the field * @param value the value */ private void htmlSetValue(HTML field, String value) { if (value == null || value.isEmpty()) field.setHTML(NOT_AVAILABLE); else field.setHTML(value); } /** * Gets the formatted size. * * @param value the value * @return the formatted size */ private String getFormattedSize(long value) { if (value > 0) { double kb = value / 1024; if (kb < 1) kb = 1; return number.format(kb); } else if (value == 0) { return EMPTY; } else return ""; } /** * Load location. * * @param fileModel the file model */ private void loadLocation(FileModel fileModel) { setPlaceholder(txtLocation, false, "loading..."); AppControllerExplorer.rpcWorkspaceService.getListParentsByItemIdentifier(fileModel.getIdentifier(), false, new AsyncCallback>() { @Override public void onFailure(Throwable caught) { GWT.log("failure get list parents by item identifier " + caught); removePlaceHolder(txtLocation); txtLocation.setHTML(NOT_AVAILABLE); // txtLocation.set(false); } @Override public void onSuccess(List result) { removePlaceHolder(txtLocation); String location = ""; if (result != null) { for (FileModel fileModel : result) { if (fileModel != null) location += "/" + fileModel.getName(); } } if (location.isEmpty()) location = "/"; txtLocation.setHTML(location); } }); } /** * Load size. * * @param itemId the item id */ private void loadSize(final String itemId) { GWT.log("Load size"); setPlaceholder(txtSize, false, "loading..."); fileSize = new Long(-1); //means is loading AppControllerExplorer.rpcWorkspaceService.loadSizeByItemId(itemId, new AsyncCallback() { @Override public void onFailure(Throwable caught) { fileSize = null; GWT.log("an error occured in load creation date by Id " + itemId + " " + caught.getMessage()); removePlaceHolder(txtSize); } @Override public void onSuccess(Long result) { GWT.log("Loaded size=" + result); fileSize = result; removePlaceHolder(txtSize); if(result!=null) htmlSetValue(txtSize, getFormattedSize(result)); else htmlSetValue(txtSize, null); } }); } /** * Load creation date. * * @param itemId the item id */ private void loadCreationDate(final String itemId) { setPlaceholder(txtCreated, false, "loading..."); AppControllerExplorer.rpcWorkspaceService.getItemCreationDateById(itemId, new AsyncCallback() { @Override public void onFailure(Throwable caught) { GWT.log("an error occured in load creation date by Id " + itemId + " " + caught.getMessage()); removePlaceHolder(txtCreated); } @Override public void onSuccess(Date dateResult) { removePlaceHolder(txtCreated); if (dateResult != null) { htmlSetValue(txtCreated, dateFormatter.format(dateResult)); }else htmlSetValue(txtCreated, null); } }); } /** * Load last modification date. * * @param itemId the item id */ private void loadLastModificationDate(final String itemId) { setPlaceholder(txtLastMofication, false, "loading..."); AppControllerExplorer.rpcWorkspaceService.loadLastModificationDateById(itemId, new AsyncCallback() { @Override public void onFailure(Throwable caught) { GWT.log("an error occured in loadLastModificationDateById " + itemId + " " + caught.getMessage()); removePlaceHolder(txtLastMofication); } @Override public void onSuccess(Date dateResult) { removePlaceHolder(txtLastMofication); if (dateResult != null) { htmlSetValue(txtLastMofication, dateFormatter.format(dateResult)); }else htmlSetValue(txtLastMofication, null); } }); } /** * Load description. * * @param identifier the identifier */ private void loadDescription(String identifier) { txtAreaDescription.setEnabled(false); AppControllerExplorer.rpcWorkspaceService.getItemDescriptionById(identifier, new AsyncCallback() { @Override public void onFailure(Throwable arg0) { txtAreaDescription.setEnabled(false); } @Override public void onSuccess(String result) { if (result != null) txtAreaDescription.setValue(result); else txtAreaDescription.setValue(""); txtAreaDescription.setEnabled(true); } }); } /** * Load gcube item properties. */ private void loadGcubeItemProperties() { // mask("Loading properties..."); AppControllerExplorer.rpcWorkspaceService.loadGcubeItemProperties(fileModel.getIdentifier(), new AsyncCallback>() { @Override public void onSuccess(Map result) { txtAreaGcubeProperties.setText(""); GWT.log("Gcube Item Properties: " + result); gCubeProperties = result; // unmask(); if (result != null && result.size() > 0) { for (String key : result.keySet()) { String text = txtAreaGcubeProperties.getText(); text += key + "=" + result.get(key) + ";\n"; txtAreaGcubeProperties.setText(text); } cgGcubeProperties.setVisible(true); } } @Override public void onFailure(Throwable caught) { // unmask(); cgGcubeProperties.setVisible(false); GWT.log("an error occured in loadGcubeItemProperties " + fileModel.getIdentifier() + " " + caught.getMessage()); } }); } /** * Load AC ls description for shared folder. * * @param sharedId the shared id */ private void loadACLsDescriptionForSharedFolder(String sharedId) { setPlaceholder(txtSharedWith, true, "loading..."); WorkspaceSharingServiceAsync.INSTANCE.getACLsDescriptionForSharedFolderId(sharedId, new AsyncCallback() { @Override public void onFailure(Throwable caught) { removePlaceHolder(txtSharedWith); txtSharedWith.setHTML("Error on recovering users"); } @Override public void onSuccess(String result) { removePlaceHolder(txtSharedWith); txtSharedWith.getElement().addClassName("shared-with-style"); GWT.log("Loaded ACLs: " + result); txtSharedWith.setHTML(result); } }); } /** * Load thumbnails for image. */ private void loadThumbnailsForImage() { htmlPanelImagePreview.setVisible(true); final HTML txtLoadingPreview = new HTML(); htmlPanelImagePreview.add(txtLoadingPreview); setPlaceholder(txtLoadingPreview, true, "loading preview..."); AppControllerExplorer.rpcWorkspaceService.getImageById(fileModel.getIdentifier(), fileModel.getGXTFolderItemType().equals(GXTFolderItemTypeEnum.IMAGE_DOCUMENT), false, new AsyncCallback() { @Override public void onFailure(Throwable caught) { removePlaceHolder(txtLoadingPreview); } @Override public void onSuccess(GWTWorkspaceItem item) { GWT.log("Image loaded: " + item.getName() + " label: " + item.getLabel() + " type: " + fileModel.getGXTFolderItemType()); if (fileModel.getGXTFolderItemType().equals(GXTFolderItemTypeEnum.IMAGE_DOCUMENT)) { GWTImageDocument theItemImage = (GWTImageDocument) item; htmlPanelImagePreview.add(new Image(theItemImage.getThumbnailUrl())); htmlPanelImagePreview.setVisible(true); }else { GWTExternalImage theExternalImage = (GWTExternalImage) item; htmlPanelImagePreview.add(new Image(theExternalImage.getThumbnailUrl())); htmlPanelImagePreview.setVisible(true); } removePlaceHolder(txtLoadingPreview); } }); } /** * Sets the placeholder. * * @param html the html * @param placeholder the placeholder */ private void setPlaceholder(HTML html, boolean spinner, String placeholder) { String loadingHMTL = placeholder; if(spinner) { loadingHMTL = ""+placeholder+""; } html.setHTML(loadingHMTL); html.getElement().addClassName("placeholder-loading"); } /** * Removes the place holder. * * @param html the html */ private void removePlaceHolder(HTML html) { html.setHTML(""); html.getElement().removeClassName("placeholder-loading"); } public static native String showPDFPreview(String pdfURL, String divId)/*-{ var theDivContainer = "#"+divId; $wnd.PDFObject.embed(pdfURL, theDivContainer); }-*/; }