/** * Copyright 2008-2016 Qualogy Solutions B.V. * * 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 com.qualogy.qafe.gwt.client.component; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.DisclosurePanel; import com.google.gwt.user.client.ui.FileUpload; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent; import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler; import com.google.gwt.user.client.ui.FormPanel.SubmitEvent; import com.google.gwt.user.client.ui.Frame; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import com.qualogy.qafe.gwt.client.context.ClientApplicationContext; import com.qualogy.qafe.gwt.client.factory.MainFactoryActions; import com.qualogy.qafe.gwt.client.images.ScrollTableOperationImages; import com.qualogy.qafe.gwt.client.service.RPCServiceAsync; import com.qualogy.qafe.gwt.client.ui.images.DataGridImageBundle; import com.qualogy.qafe.gwt.client.ui.renderer.RendererHelper; import com.qualogy.qafe.gwt.client.vo.functions.DataContainerGVO; import com.qualogy.qafe.gwt.client.vo.functions.execute.FunctionsExecutor; import com.qualogy.qafe.gwt.client.vo.ui.ImageGVO; /** * A panel that wraps a {@link QPagingScrollTable} and includes operations to * perform operations on the Qpagingscrolltable */ public class QPagingScrollTableOperation extends Composite { public final static String CONTROLS_DELETE="delete"; public final static String CONTROLS_ADD="add"; public final static String CONTROLS_SAVE="save"; public final static String CONTROLS_REFRESH="refresh"; public final static String CONTROLS_CANCEL="cancel"; public final static String STYLE_DELETE="Delete"; public final static String STYLE_ADD="Add"; public final static String STYLE_SAVE="Save"; public final static String STYLE_REFRESH="Refresh"; public final static String STYLE_CANCEL="Cancel"; /** * The default style name. */ public static final String DEFAULT_STYLENAME = "gwt-PagingOptions"; public static final String STYLENAME_PREFIX = "pagingOptions"; /** * The label used to display errors. */ private HTML errorLabel; private Image addImage; private Image deleteImage; private Image saveImage; private Image refreshImage; private Image cancelImage; /** * The table being affected. */ private QPagingScrollTable table; /** Mapping between supported export formats and labels to be displayed on screen. */ private HashMap<String, String> labelsMap; /** Mapping between supported export formats labels and images. */ private HashMap<String, Image> imageMap; /** * Constructor. * * @param table * the table being ad */ public QPagingScrollTableOperation(QPagingScrollTable table) { this(table, GWT.<ScrollTableOperationImages> create(ScrollTableOperationImages.class)); } /** * Constructor. * * @param table * the table being affected * @param images * the images to use */ // CHECKSTYLE.OFF: CyclomaticComplexity public QPagingScrollTableOperation(final QPagingScrollTable table, ScrollTableOperationImages images) { this.table = table; if (this.table instanceof QPagingScrollTable){ this.table.setScrollTableOperations(this); } // Create the main widget HorizontalPanel hPanel = new HorizontalPanel(); initWidget(hPanel); hPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); setStyleName(DEFAULT_STYLENAME); // Create the paging image buttons createPageButtons(images); // Create the error label errorLabel = new HTML(); errorLabel.setStylePrimaryName("errorMessage"); // Add the widgets to the panel hPanel.add(createSpacer()); if (hasAddControl(table)){ hPanel.add(addImage); hPanel.add(createSpacer()); } if (hasDeleteControl(table)){ hPanel.add(deleteImage); hPanel.add(createSpacer()); } if (isEditableDatagrid(table) || hasDeleteControl(table) || hasAddControl(table)){ if (saveDatagrid(table)) { hPanel.add(saveImage); hPanel.add(createSpacer()); } if (refreshDatagrid(table)){ hPanel.add(refreshImage); hPanel.add(createSpacer()); } if (cancelDatagrid(table)){ hPanel.add(cancelImage); hPanel.add(createSpacer()); } } hPanel.add(errorLabel); if (table.getSource().getImportEnabled()!=null && table.getSource().getImportEnabled().booleanValue()){ createFormComposite(hPanel); } if (table.getSource() != null && table.getSource().getExport() != null && table.getSource().getExport().booleanValue()) { createExportComposite(table, hPanel); } } // CHECKSTYLE.ON: CyclomaticComplexity private void createExportComposite(final QPagingScrollTable table, HorizontalPanel hPanel) { createExportLabelsAndImages(); final DisclosurePanel exportPanel = new DisclosurePanel("Export"); String[] labels = getExportLabels(table.getSource().getExportFormats()); Image[] exportImages = getExportImages(labels); FlexTable gridExportPanel = new FlexTable(); hPanel.add(exportPanel); exportPanel.add(gridExportPanel); final Frame frame = new Frame(); frame.setHeight("0"); frame.setWidth("0"); frame.setVisible(false); final String moduleRelativeURL = GWT.getModuleBaseURL() + "/rpc.export"; gridExportPanel.setWidget(0,0,frame); final CheckBox generateColumnHeaderBox= new CheckBox("Generate Column Header"); gridExportPanel.getFlexCellFormatter().setColSpan(1,1, 7); gridExportPanel.setWidget(2, 1,generateColumnHeaderBox); gridExportPanel.getFlexCellFormatter().setColSpan(2,1,6); for (int i = 0; i < labels.length; i++) { exportImages[i].setStylePrimaryName("datagridexportlabel"); exportImages[i].setTitle(labels[i]); gridExportPanel.setWidget(0, i+1,exportImages[i]); exportImages[i].addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (event.getSource() instanceof Image) { Image image = (Image) (event.getSource()); final String exportCode = image.getTitle(); RPCServiceAsync service = MainFactoryActions.createService(); AsyncCallback<?> callback = new AsyncCallback<Object>() { @Override public void onSuccess(Object result) { String uuid = (String) result; // set frame frame.setUrl(moduleRelativeURL + "?uuid=" + uuid); ClientApplicationContext.getInstance().setBusy(false); } @Override public void onFailure(Throwable caught) { ClientApplicationContext.getInstance().log("Export failed", "Export failed for " + exportCode + " ", true, true, caught); ClientApplicationContext.getInstance().setBusy(false); FunctionsExecutor.setProcessedBuiltIn(true); } }; List<DataContainerGVO> dList = new ArrayList<DataContainerGVO>(); // following loop is to maintain the order of rows while exporting. for(int i=0;i<(table.getAbsoluteLastRowIndex()+1);i++){ dList.add(table.getRowValue(i)); } service.prepareForExport(dList, exportCode, null, generateColumnHeaderBox.getValue().booleanValue(), callback); } } }); } } private void createFormComposite(HorizontalPanel hPanel) { final DisclosurePanel importPanel = new DisclosurePanel("Upload data"); hPanel.add(importPanel); final FormPanel formPanel = new FormPanel(); formPanel.setAction(GWT.getModuleBaseURL() + "/rpc.datagridupload"); formPanel.setEncoding(FormPanel.ENCODING_MULTIPART); formPanel.setMethod(FormPanel.METHOD_POST); FileUpload fileUploadComponent = new FileUpload(); fileUploadComponent.setName("uploadElement"); Button uploadButtonComponent = new Button("Upload"); uploadButtonComponent.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { formPanel.submit(); } }); CheckBox isFirstLineHeader = new CheckBox("Is first row header ?"); isFirstLineHeader.setName("isFirstLineHeader"); isFirstLineHeader.setTitle("Check wheter or not the first line of the uploaded file is a header/column definition"); HorizontalPanel hp = new HorizontalPanel(); Label label = new Label("Delimeter"); final TextBox delimiter = new TextBox(); delimiter.setValue(","); delimiter.setTitle("Insert the delimeter (can be any value, as long it's length 1)"); delimiter.setName("delimiter"); delimiter.setWidth("15px"); hp.setSpacing(10); hp.add(label); hp.add(delimiter); Grid gridPanel = new Grid(2, 4); gridPanel.setWidget(0, 0, fileUploadComponent); gridPanel.setWidget(0, 1, uploadButtonComponent); gridPanel.setWidget(1, 0, isFirstLineHeader); gridPanel.setWidget(1, 1, hp); formPanel.add(gridPanel); formPanel.addSubmitHandler(new FormPanel.SubmitHandler() { @Override public void onSubmit(SubmitEvent event) { // This event is fired just before the form is submitted. We can // take // this opportunity to perform validation. if (delimiter.getText().length() == 0 || delimiter.getText().length() > 1) { ClientApplicationContext.getInstance().log("Ooops...Delimeter invalid", "Make sure there is valid delimeter value.One character only (current value ='" + delimiter.getText() + "'", true); event.cancel(); } } }); formPanel.addSubmitCompleteHandler(new SubmitCompleteHandler() { @Override public void onSubmitComplete(SubmitCompleteEvent event) { String uuId = event.getResults(); if (uuId != null && uuId.indexOf("=") > 0) { uuId = uuId.substring(uuId.indexOf("=") + 1); processData(uuId); importPanel.setOpen(false); } else { ClientApplicationContext.getInstance().log("Upload failed", event.getResults(), true); } } }); importPanel.add(formPanel); } /** * Create two maps to map the supported export formats with their corresponding labels and images */ private void createExportLabelsAndImages() { labelsMap = new HashMap<String, String>(); labelsMap.put("csv", "CSV"); labelsMap.put("excel", "Excel"); labelsMap.put("pdf", "PDF"); labelsMap.put("xml", "XML"); DataGridImageBundle dib =ClientApplicationContext.getInstance().getDatagridImageBundle(); imageMap = new HashMap<String, Image>(); imageMap.put("CSV", dib.iconExportCSV().createImage()); imageMap.put("Excel", dib.iconExportExcel().createImage()); imageMap.put("XML", dib.iconExportXML().createImage()); imageMap.put("PDF", dib.iconExportPDF().createImage()); } /** * Convert the export formats into labels to display. * @param exportFormats A comma separated list of possible export formats * @return an array of labels */ private String[] getExportLabels(String exportFormats) { String[] exportTypes = exportFormats.split(","); String[] labels = new String[exportTypes.length]; for (int i = 0; i < labels.length; i ++) { labels[i] = labelsMap.get(exportTypes[i]); } return labels; } /** * Create an array of images, one for every supported export type (i.e. labels) * @param labels * @return array of images */ private Image[] getExportImages(String[] labels) { Image[] images = new Image[labels.length]; for (int i = 0; i < labels.length; i ++) { images[i] = imageMap.get(labels[i]); } return images; } private boolean hasDeleteControl(final QPagingScrollTable table) { return table.getSource().getDelete()!=null && table.getSource().getDelete().booleanValue(); } private boolean hasAddControl(final QPagingScrollTable table) { return table.getSource().getAdd()!=null && table.getSource().getAdd().booleanValue(); } private boolean isEditableDatagrid(final QPagingScrollTable table) { return table.getSource().getEditable()!=null && table.getSource().getEditable().booleanValue(); } private boolean saveDatagrid(final QPagingScrollTable table) { return table.getSource().getSave(); } private boolean cancelDatagrid(final QPagingScrollTable table) { return table.getSource().getCancel(); } private boolean refreshDatagrid(final QPagingScrollTable table) { return table.getSource().getRefresh(); } protected void processData(String uuid) { ClientApplicationContext.getInstance().setBusy(true); RPCServiceAsync service = MainFactoryActions.createService(); AsyncCallback<?> callback = new AsyncCallback<Object>() { @Override public void onSuccess(Object result) { List<DataContainerGVO> map = (List<DataContainerGVO>) result; table.insertImportedData(map); // WindowFactory.createWindow(ui, windowId); ClientApplicationContext.getInstance().setBusy(false); FunctionsExecutor.setProcessedBuiltIn(true); } @Override public void onFailure(Throwable caught) { ClientApplicationContext.getInstance().log("Getting window from server failed", "Error getting data after upload", true, true, caught); ClientApplicationContext.getInstance().setBusy(false); FunctionsExecutor.setProcessedBuiltIn(true); } }; service.getDataForDatagridFromUpload(uuid, callback); } /** * @return the {@link QPagingScrollTable}. */ public QPagingScrollTable getPagingScrollTable() { return table; } /** * Create a widget that can be used to add space. * * @return a spacer widget */ protected Widget createSpacer() { return new HTML("  "); } /** * Create a paging image buttons. * * @param images * the images to use */ private void createPageButtons(ScrollTableOperationImages images) { addImage = images.scrolltableOperationAdd().createImage(); addImage.addStyleName(STYLENAME_PREFIX + STYLE_ADD); deleteImage = images.scrolltableOperationDelete().createImage(); deleteImage.addStyleName(STYLENAME_PREFIX + STYLE_DELETE); // Create the images if (saveDatagrid(table)) { saveImage = images.scrolltableOperationSave().createImage(); saveImage.addStyleName(STYLENAME_PREFIX + STYLE_SAVE); } if (refreshDatagrid(table)){ refreshImage = images.scrolltableOperationRefresh().createImage(); refreshImage.addStyleName(STYLENAME_PREFIX + STYLE_REFRESH); } if (cancelDatagrid(table)){ cancelImage = images.scrolltableOperationCancel().createImage(); cancelImage.addStyleName(STYLENAME_PREFIX + STYLE_CANCEL); } // Create the listener ClickHandler handler = new ClickHandler() { @Override public void onClick(ClickEvent event) { Object source = event.getSource(); if (source == addImage) { table.onAdd(); } else if (source == deleteImage) { table.onDelete(); } else if (source == saveImage) { table.onSave(); } else if (source == refreshImage) { table.onRefresh(); } else if (source == cancelImage) { table.onCancel(); } } }; // Add the listener to each image addImage.addClickHandler(handler); deleteImage.addClickHandler(handler); if (saveImage != null){ saveImage.addClickHandler(handler); } if (refreshImage != null){ refreshImage.addClickHandler(handler); } if (cancelImage != null){ cancelImage.addClickHandler(handler); } } public void initForCallback(String gridId, String uuid, String parent, String context) { ImageGVO imageDelete = createImageGVO(gridId + "." + CONTROLS_DELETE); ImageGVO imageAdd = createImageGVO(gridId + "." + CONTROLS_ADD); ImageGVO imageSave = createImageGVO(gridId + "." + CONTROLS_SAVE); ImageGVO imageRefresh = createImageGVO(gridId + "." + CONTROLS_REFRESH); ImageGVO imageCancel = createImageGVO(gridId + "." + CONTROLS_CANCEL); RendererHelper.fillIn(imageDelete, getDeleteImage(), uuid, parent, context); RendererHelper.fillIn(imageAdd, getAddImage(), uuid, parent, context); RendererHelper.fillIn(imageSave, getSaveImage(), uuid, parent, context); RendererHelper.fillIn(imageRefresh, getRefreshImage(), uuid, parent, context); RendererHelper.fillIn(imageCancel, getCancelImage(), uuid, parent, context); } private ImageGVO createImageGVO(String id) { ImageGVO imageGVO = new ImageGVO(); imageGVO.setId(id); return imageGVO; } public Image getDeleteImage() { return deleteImage; } public void setDeleteImage(Image deleteImage) { this.deleteImage = deleteImage; } public Image getAddImage() { return addImage; } public void setAddImage(Image addImage) { this.addImage = addImage; } public Image getSaveImage() { return saveImage; } public void setSaveImage(Image saveImage) { this.saveImage = saveImage; } public Image getRefreshImage() { return refreshImage; } public void setRefreshImage(Image refreshImage) { this.refreshImage = refreshImage; } public Image getCancelImage() { return cancelImage; } public void setCancelImage(Image cancelImage) { this.cancelImage = cancelImage; } }