/*******************************************************************************
* Copyright (c) 2011, 2016 Eurotech and/or its affiliates
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eurotech
*******************************************************************************/
package org.eclipse.kura.web.client.ui.Settings;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.kura.web.client.messages.Messages;
import org.eclipse.kura.web.client.ui.EntryClassUi;
import org.eclipse.kura.web.client.ui.Tab;
import org.eclipse.kura.web.client.util.FailureHandler;
import org.eclipse.kura.web.shared.GwtKuraErrorCode;
import org.eclipse.kura.web.shared.GwtKuraException;
import org.eclipse.kura.web.shared.model.GwtSnapshot;
import org.eclipse.kura.web.shared.model.GwtXSRFToken;
import org.eclipse.kura.web.shared.service.GwtSecurityTokenService;
import org.eclipse.kura.web.shared.service.GwtSecurityTokenServiceAsync;
import org.eclipse.kura.web.shared.service.GwtSnapshotService;
import org.eclipse.kura.web.shared.service.GwtSnapshotServiceAsync;
import org.gwtbootstrap3.client.ui.Alert;
import org.gwtbootstrap3.client.ui.Button;
import org.gwtbootstrap3.client.ui.Modal;
import org.gwtbootstrap3.client.ui.ModalBody;
import org.gwtbootstrap3.client.ui.ModalFooter;
import org.gwtbootstrap3.client.ui.gwt.CellTable;
import org.gwtbootstrap3.client.ui.html.Span;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.URL;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FileUpload;
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.Hidden;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SingleSelectionModel;
public class SnapshotsTabUi extends Composite implements Tab {
private static SnapshotsTabUiUiBinder uiBinder = GWT.create(SnapshotsTabUiUiBinder.class);
private static final Logger logger = Logger.getLogger(SnapshotsTabUi.class.getSimpleName());
interface SnapshotsTabUiUiBinder extends UiBinder<Widget, SnapshotsTabUi> {
}
private static final Messages MSGS = GWT.create(Messages.class);
private final GwtSecurityTokenServiceAsync gwtXSRFService = GWT.create(GwtSecurityTokenService.class);
private final GwtSnapshotServiceAsync gwtSnapshotService = GWT.create(GwtSnapshotService.class);
private final static String SERVLET_URL = "/" + GWT.getModuleName() + "/file/configuration/snapshot";
@UiField
Modal uploadModal;
@UiField
FormPanel snapshotsForm;
@UiField
Button uploadCancel, uploadUpload;
@UiField
Button refresh, download, rollback, upload;
@UiField
Alert notification;
@UiField
FileUpload filePath;
@UiField
Hidden xsrfTokenField;
@UiField
CellTable<GwtSnapshot> snapshotsGrid = new CellTable<GwtSnapshot>();
private Element downloadIframe;
private final ListDataProvider<GwtSnapshot> snapshotsDataProvider = new ListDataProvider<GwtSnapshot>();
final SingleSelectionModel<GwtSnapshot> selectionModel = new SingleSelectionModel<GwtSnapshot>();
GwtSnapshot selected;
public SnapshotsTabUi() {
logger.log(Level.FINER, "Initiating SnapshotsTabUI...");
initWidget(uiBinder.createAndBindUi(this));
initTable();
this.snapshotsGrid.setSelectionModel(this.selectionModel);
initDownloadIframe();
initInterfaceButtons();
initUploadModalHandlers();
this.snapshotsForm.addSubmitCompleteHandler(new SubmitCompleteHandler() {
@Override
public void onSubmitComplete(SubmitCompleteEvent event) {
String htmlResponse = event.getResults();
EntryClassUi.hideWaitModal();
if (htmlResponse == null || htmlResponse.isEmpty()) {
logger.log(Level.FINER, MSGS.information() + ": " + MSGS.fileUploadSuccess());
refresh();
} else {
logger.log(Level.SEVERE, MSGS.information() + ": " + MSGS.fileUploadFailure());
FailureHandler.handle(new GwtKuraException(GwtKuraErrorCode.INTERNAL_ERROR));
}
}
});
}
@Override
public void setDirty(boolean flag) {
}
@Override
public boolean isDirty() {
return false;
}
@Override
public boolean isValid() {
return true;
}
@Override
public void refresh() {
this.notification.setVisible(false);
EntryClassUi.showWaitModal();
this.gwtXSRFService.generateSecurityToken(new AsyncCallback<GwtXSRFToken>() {
@Override
public void onFailure(Throwable ex) {
EntryClassUi.hideWaitModal();
FailureHandler.handle(ex);
}
@Override
public void onSuccess(GwtXSRFToken token) {
SnapshotsTabUi.this.gwtSnapshotService.findDeviceSnapshots(token,
new AsyncCallback<ArrayList<GwtSnapshot>>() {
@Override
public void onFailure(Throwable ex) {
EntryClassUi.hideWaitModal();
FailureHandler.handle(ex);
}
@Override
public void onSuccess(ArrayList<GwtSnapshot> result) {
SnapshotsTabUi.this.snapshotsDataProvider.getList().clear();
for (GwtSnapshot pair : result) {
SnapshotsTabUi.this.snapshotsDataProvider.getList().add(pair);
}
int snapshotsDataSize = SnapshotsTabUi.this.snapshotsDataProvider.getList().size();
if (snapshotsDataSize == 0) {
SnapshotsTabUi.this.snapshotsGrid.setVisible(false);
SnapshotsTabUi.this.notification.setVisible(true);
SnapshotsTabUi.this.notification.setText("No Snapshots Available");
SnapshotsTabUi.this.download.setEnabled(false);
SnapshotsTabUi.this.rollback.setEnabled(false);
} else {
SnapshotsTabUi.this.snapshotsGrid.setVisibleRange(0, snapshotsDataSize);
SnapshotsTabUi.this.snapshotsGrid.setVisible(true);
SnapshotsTabUi.this.notification.setVisible(false);
SnapshotsTabUi.this.download.setEnabled(true);
SnapshotsTabUi.this.rollback.setEnabled(true);
}
SnapshotsTabUi.this.snapshotsDataProvider.flush();
EntryClassUi.hideWaitModal();
}
});
}
});
}
private void initTable() {
TextColumn<GwtSnapshot> col1 = new TextColumn<GwtSnapshot>() {
@Override
public String getValue(GwtSnapshot object) {
return String.valueOf(object.getSnapshotId());
}
};
col1.setCellStyleNames("status-table-row");
this.snapshotsGrid.addColumn(col1, MSGS.deviceSnapshotId());
TextColumn<GwtSnapshot> col2 = new TextColumn<GwtSnapshot>() {
@Override
public String getValue(GwtSnapshot object) {
return String.valueOf(object.get("createdOnFormatted"));
}
};
col2.setCellStyleNames("status-table-row");
this.snapshotsGrid.addColumn(col2, MSGS.deviceSnapshotCreatedOn());
this.snapshotsDataProvider.addDataDisplay(this.snapshotsGrid);
}
private void initUploadModalHandlers() {
this.uploadCancel.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
SnapshotsTabUi.this.uploadModal.hide();
}
});
this.uploadUpload.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
SnapshotsTabUi.this.gwtXSRFService.generateSecurityToken(new AsyncCallback<GwtXSRFToken>() {
@Override
public void onFailure(Throwable ex) {
FailureHandler.handle(ex);
}
@Override
public void onSuccess(GwtXSRFToken token) {
SnapshotsTabUi.this.xsrfTokenField.setValue(token.getToken());
SnapshotsTabUi.this.snapshotsForm.submit();
SnapshotsTabUi.this.uploadModal.hide();
EntryClassUi.showWaitModal();
}
});
}
});
}
private void initInterfaceButtons() {
this.refresh.setText(MSGS.refresh());
this.refresh.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
refresh();
}
});
this.download.setText(MSGS.download());
this.download.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
SnapshotsTabUi.this.selected = SnapshotsTabUi.this.selectionModel.getSelectedObject();
if (SnapshotsTabUi.this.selected != null) {
// please see
// http://stackoverflow.com/questions/13277752/gwt-open-window-after-rpc-is-prevented-by-popup-blocker
SnapshotsTabUi.this.gwtXSRFService.generateSecurityToken(new AsyncCallback<GwtXSRFToken>() {
@Override
public void onFailure(Throwable ex) {
FailureHandler.handle(ex);
}
@Override
public void onSuccess(GwtXSRFToken token) {
downloadSnapshot(token.getToken());
}
});
}
}
});
this.rollback.setText(MSGS.rollback());
this.rollback.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
rollback();
}
});
this.upload.setText(MSGS.upload());
this.upload.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
uploadAndApply();
}
});
}
private native void initDownloadIframe() /*-{
var iframe = document.createElement('iframe');
iframe.style.display = 'none'
document.getElementsByTagName('body')[0].appendChild(iframe);
this.@org.eclipse.kura.web.client.ui.Settings.SnapshotsTabUi::downloadIframe = iframe;
}-*/;
private void rollback() {
final GwtSnapshot snapshot = this.selectionModel.getSelectedObject();
if (snapshot != null) {
final Modal rollbackModal = new Modal();
ModalBody rollbackModalBody = new ModalBody();
ModalFooter rollbackModalFooter = new ModalFooter();
rollbackModal.setTitle(MSGS.confirm());
rollbackModal.setClosable(true);
rollbackModalBody.add(new Span(MSGS.deviceSnapshotRollbackConfirm()));
rollbackModalFooter.add(new Button("Yes", new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
EntryClassUi.showWaitModal();
SnapshotsTabUi.this.gwtXSRFService.generateSecurityToken(new AsyncCallback<GwtXSRFToken>() {
@Override
public void onFailure(Throwable ex) {
EntryClassUi.hideWaitModal();
FailureHandler.handle(ex);
}
@Override
public void onSuccess(GwtXSRFToken token) {
SnapshotsTabUi.this.gwtSnapshotService.rollbackDeviceSnapshot(token, snapshot,
new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable ex) {
EntryClassUi.hideWaitModal();
FailureHandler.handle(ex);
}
@Override
public void onSuccess(Void result) {
EntryClassUi.hideWaitModal();
refresh();
}
});
}
});
rollbackModal.hide();
}
}));
rollbackModalFooter.add(new Button("No", new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
rollbackModal.hide();
}
}));
rollbackModal.add(rollbackModalBody);
rollbackModal.add(rollbackModalFooter);
rollbackModal.show();
}
}
private void downloadSnapshot(String tokenId) {
final StringBuilder sbUrl = new StringBuilder();
Long snapshot = this.selected.getSnapshotId();
sbUrl.append("/" + GWT.getModuleName() + "/device_snapshots?").append("snapshotId=").append(snapshot)
.append("&").append("xsrfToken=").append(URL.encodeQueryString(tokenId));
downloadFile(sbUrl.toString());
}
private native void downloadFile(String url) /*-{
var downloadIframe = this.@org.eclipse.kura.web.client.ui.Settings.SnapshotsTabUi::downloadIframe;
downloadIframe.setAttribute('src', url);
}-*/;
private void uploadAndApply() {
this.uploadModal.show();
this.uploadModal.setTitle(MSGS.upload());
this.snapshotsForm.setEncoding(FormPanel.ENCODING_MULTIPART);
this.snapshotsForm.setMethod(FormPanel.METHOD_POST);
this.snapshotsForm.setAction(SERVLET_URL);
this.filePath.setName("uploadedFile");
this.xsrfTokenField.setID("xsrfToken");
this.xsrfTokenField.setName("xsrfToken");
this.xsrfTokenField.setValue("");
}
}