/*******************************************************************************
* Copyright (c) 2011, 2016 Eurotech and/or its affiliates and others
*
* 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
* Red Hat Inc
*******************************************************************************/
package org.eclipse.kura.web.client.ui;
import java.util.Date;
import java.util.List;
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.CloudServices.CloudServicesUi;
import org.eclipse.kura.web.client.ui.Device.DevicePanelUi;
import org.eclipse.kura.web.client.ui.Firewall.FirewallPanelUi;
import org.eclipse.kura.web.client.ui.Network.NetworkPanelUi;
import org.eclipse.kura.web.client.ui.Packages.PackagesPanelUi;
import org.eclipse.kura.web.client.ui.Settings.SettingsPanelUi;
import org.eclipse.kura.web.client.ui.Status.StatusPanelUi;
import org.eclipse.kura.web.client.util.FailureHandler;
import org.eclipse.kura.web.shared.model.GwtConfigComponent;
import org.eclipse.kura.web.shared.model.GwtSession;
import org.eclipse.kura.web.shared.model.GwtXSRFToken;
import org.eclipse.kura.web.shared.service.GwtComponentService;
import org.eclipse.kura.web.shared.service.GwtComponentServiceAsync;
import org.eclipse.kura.web.shared.service.GwtPackageService;
import org.eclipse.kura.web.shared.service.GwtPackageServiceAsync;
import org.eclipse.kura.web.shared.service.GwtSecurityTokenService;
import org.eclipse.kura.web.shared.service.GwtSecurityTokenServiceAsync;
import org.gwtbootstrap3.client.shared.event.ModalHideEvent;
import org.gwtbootstrap3.client.shared.event.ModalHideHandler;
import org.gwtbootstrap3.client.ui.AnchorListItem;
import org.gwtbootstrap3.client.ui.Button;
import org.gwtbootstrap3.client.ui.Heading;
import org.gwtbootstrap3.client.ui.Icon;
import org.gwtbootstrap3.client.ui.Modal;
import org.gwtbootstrap3.client.ui.ModalBody;
import org.gwtbootstrap3.client.ui.ModalFooter;
import org.gwtbootstrap3.client.ui.ModalHeader;
import org.gwtbootstrap3.client.ui.NavPills;
import org.gwtbootstrap3.client.ui.Panel;
import org.gwtbootstrap3.client.ui.PanelBody;
import org.gwtbootstrap3.client.ui.TabListItem;
import org.gwtbootstrap3.client.ui.constants.IconSize;
import org.gwtbootstrap3.client.ui.constants.IconType;
import org.gwtbootstrap3.client.ui.html.Span;
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.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.logging.client.HasWidgetsLogHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
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.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
public class EntryClassUi extends Composite {
interface EntryClassUIUiBinder extends UiBinder<Widget, EntryClassUi> {
}
private static EntryClassUIUiBinder uiBinder = GWT.create(EntryClassUIUiBinder.class);
private static final Messages MSGS = GWT.create(Messages.class);
private static final Logger logger = Logger.getLogger(EntryClassUi.class.getSimpleName());
private static Logger errorLogger = Logger.getLogger("ErrorLogger");
private final StatusPanelUi statusBinder = GWT.create(StatusPanelUi.class);
private final DevicePanelUi deviceBinder = GWT.create(DevicePanelUi.class);
private final PackagesPanelUi packagesBinder = GWT.create(PackagesPanelUi.class);
private final SettingsPanelUi settingsBinder = GWT.create(SettingsPanelUi.class);
private final FirewallPanelUi firewallBinder = GWT.create(FirewallPanelUi.class);
private final NetworkPanelUi networkBinder = GWT.create(NetworkPanelUi.class);
private final CloudServicesUi cloudServicesBinder = GWT.create(CloudServicesUi.class);
private final GwtPackageServiceAsync gwtPackageService = GWT.create(GwtPackageService.class);
private final GwtComponentServiceAsync gwtComponentService = GWT.create(GwtComponentService.class);
private final GwtSecurityTokenServiceAsync gwtXSRFService = GWT.create(GwtSecurityTokenService.class);
public GwtConfigComponent selected = null;
static PopupPanel m_waitModal;
GwtSession currentSession;
AnchorListItem service;
GwtConfigComponent addedItem;
EntryClassUi ui;
Modal modal;
ServicesUi servicesUi;
private boolean servicesDirty;
private boolean networkDirty;
private boolean firewallDirty;
private boolean settingsDirty;
private boolean cloudServicesDirty;
@UiField
Panel header;
@UiField
Label footerLeft, footerCenter, footerRight;
@UiField
Panel contentPanel;
@UiField
Heading contentPanelHeader;
@UiField
PanelBody contentPanelBody;
@UiField
TabListItem status;
@UiField
AnchorListItem device;
@UiField
AnchorListItem network;
@UiField
AnchorListItem firewall;
@UiField
AnchorListItem packages;
@UiField
AnchorListItem settings;
@UiField
AnchorListItem cloudServices;
@UiField
ScrollPanel servicesPanel;
@UiField
NavPills servicesMenu;
@UiField
VerticalPanel errorLogArea;
@UiField
Modal errorPopup;
public EntryClassUi() {
logger.log(Level.FINER, "Initiating UiBinder");
this.ui = this;
initWidget(uiBinder.createAndBindUi(this));
// TODO : standardize the URL?
// header.setUrl("eclipse/kura/icons/kura_logo_small.png");
this.header.setStyleName("headerLogo");
Date now = new Date();
@SuppressWarnings("deprecation")
int year = now.getYear() + 1900;
this.footerLeft.setText(MSGS.copyright(String.valueOf(year)));
this.footerLeft.setStyleName("copyright");
this.contentPanel.setVisible(false);
// Set client side logging
errorLogger.addHandler(new HasWidgetsLogHandler(this.errorLogArea));
this.errorPopup.addHideHandler(new ModalHideHandler() {
@Override
public void onHide(ModalHideEvent evt) {
EntryClassUi.this.errorLogArea.clear();
}
});
//
dragDropInit(this);
FailureHandler.setPopup(this.errorPopup);
}
public void setSession(GwtSession GwtSession) {
this.currentSession = GwtSession;
}
public void setFooter(GwtSession GwtSession) {
this.footerRight.setText(GwtSession.getKuraVersion());
if (GwtSession.isDevelopMode()) {
this.footerCenter.setText(MSGS.developmentMode());
}
}
public void initSystemPanel(GwtSession GwtSession, boolean connectionStatus) {
final EntryClassUi m_instanceReference = this;
if (!GwtSession.isNetAdminAvailable()) {
this.network.setVisible(false);
this.firewall.setVisible(false);
}
// Status Panel
updateConnectionStatusImage(connectionStatus);
this.status.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Button b = new Button(MSGS.yesButton(), new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (EntryClassUi.this.modal != null) {
EntryClassUi.this.modal.hide();
}
EntryClassUi.this.contentPanel.setVisible(true);
EntryClassUi.this.contentPanelHeader.setText("Status");
EntryClassUi.this.contentPanelBody.clear();
EntryClassUi.this.contentPanelBody.add(EntryClassUi.this.statusBinder);
EntryClassUi.this.statusBinder.setSession(EntryClassUi.this.currentSession);
EntryClassUi.this.statusBinder.setParent(m_instanceReference);
EntryClassUi.this.statusBinder.loadStatusData();
}
});
renderDirtyConfigModal(b);
}
});
// Device Panel
this.device.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Button b = new Button(MSGS.yesButton(), new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
forceTabsCleaning();
if (EntryClassUi.this.modal != null) {
EntryClassUi.this.modal.hide();
}
EntryClassUi.this.contentPanel.setVisible(true);
EntryClassUi.this.contentPanelHeader.setText(MSGS.device());
EntryClassUi.this.contentPanelBody.clear();
EntryClassUi.this.contentPanelBody.add(EntryClassUi.this.deviceBinder);
EntryClassUi.this.deviceBinder.setSession(EntryClassUi.this.currentSession);
EntryClassUi.this.deviceBinder.initDevicePanel();
}
});
renderDirtyConfigModal(b);
}
});
// Network Panel
if (this.network.isVisible()) {
this.network.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Button b = new Button(MSGS.yesButton(), new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
forceTabsCleaning();
if (EntryClassUi.this.modal != null) {
EntryClassUi.this.modal.hide();
}
EntryClassUi.this.contentPanel.setVisible(true);
EntryClassUi.this.contentPanelHeader.setText(MSGS.network());
EntryClassUi.this.contentPanelBody.clear();
EntryClassUi.this.contentPanelBody.add(EntryClassUi.this.networkBinder);
EntryClassUi.this.networkBinder.setSession(EntryClassUi.this.currentSession);
EntryClassUi.this.networkBinder.initNetworkPanel();
}
});
renderDirtyConfigModal(b);
}
});
}
// Firewall Panel
if (this.firewall.isVisible()) {
this.firewall.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Button b = new Button(MSGS.yesButton(), new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
forceTabsCleaning();
if (EntryClassUi.this.modal != null) {
EntryClassUi.this.modal.hide();
}
EntryClassUi.this.contentPanel.setVisible(true);
EntryClassUi.this.contentPanelHeader.setText(MSGS.firewall());
EntryClassUi.this.contentPanelBody.clear();
EntryClassUi.this.contentPanelBody.add(EntryClassUi.this.firewallBinder);
EntryClassUi.this.firewallBinder.initFirewallPanel();
}
});
renderDirtyConfigModal(b);
}
});
}
// Packages Panel
this.packages.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Button b = new Button(MSGS.yesButton(), new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
forceTabsCleaning();
if (EntryClassUi.this.modal != null) {
EntryClassUi.this.modal.hide();
}
EntryClassUi.this.contentPanel.setVisible(true);
EntryClassUi.this.contentPanelHeader.setText(MSGS.packages());
EntryClassUi.this.contentPanelBody.clear();
EntryClassUi.this.contentPanelBody.add(EntryClassUi.this.packagesBinder);
EntryClassUi.this.packagesBinder.setSession(EntryClassUi.this.currentSession);
EntryClassUi.this.packagesBinder.setMainUi(EntryClassUi.this.ui);
EntryClassUi.this.packagesBinder.refresh();
}
});
renderDirtyConfigModal(b);
}
});
// Settings Panel
this.settings.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Button b = new Button(MSGS.yesButton(), new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
forceTabsCleaning();
if (EntryClassUi.this.modal != null) {
EntryClassUi.this.modal.hide();
}
EntryClassUi.this.contentPanel.setVisible(true);
EntryClassUi.this.contentPanelHeader.setText(MSGS.settings());
EntryClassUi.this.contentPanelBody.clear();
EntryClassUi.this.contentPanelBody.add(EntryClassUi.this.settingsBinder);
EntryClassUi.this.settingsBinder.setSession(EntryClassUi.this.currentSession);
EntryClassUi.this.settingsBinder.load();
}
});
renderDirtyConfigModal(b);
}
});
// Cloud services Panel
this.cloudServices.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Button b = new Button(MSGS.yesButton(), new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
forceTabsCleaning();
if (EntryClassUi.this.modal != null) {
EntryClassUi.this.modal.hide();
}
EntryClassUi.this.contentPanel.setVisible(true);
EntryClassUi.this.contentPanelHeader.setText(MSGS.cloudServices());
EntryClassUi.this.contentPanelBody.clear();
EntryClassUi.this.contentPanelBody.add(EntryClassUi.this.cloudServicesBinder);
EntryClassUi.this.cloudServicesBinder.refresh();
}
});
renderDirtyConfigModal(b);
}
});
}
public void initServicesTree() {
// (Re)Fetch Available Services
this.gwtXSRFService.generateSecurityToken(new AsyncCallback<GwtXSRFToken>() {
@Override
public void onFailure(Throwable ex) {
FailureHandler.handle(ex, EntryClassUi.class.getName());
}
@Override
public void onSuccess(GwtXSRFToken token) {
EntryClassUi.this.gwtComponentService.findServicesConfigurations(token,
new AsyncCallback<List<GwtConfigComponent>>() {
@Override
public void onFailure(Throwable ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
FailureHandler.handle(ex, EntryClassUi.class.getName());
}
@Override
public void onSuccess(List<GwtConfigComponent> result) {
EntryClassUi.this.servicesMenu.clear();
for (GwtConfigComponent pair : result) {
EntryClassUi.this.servicesMenu.add(new ServicesAnchorListItem(pair, EntryClassUi.this.ui));
}
}
});
}
});
}
public void render(GwtConfigComponent item) {
// Do everything Content Panel related in ServicesUi
this.contentPanelBody.clear();
this.servicesUi = new ServicesUi(item, this);
this.contentPanel.setVisible(true);
if (item != null) {
this.contentPanelHeader.setText(item.getComponentName());
}
this.contentPanelBody.add(this.servicesUi);
}
public void updateConnectionStatusImage(boolean isConnected) {
String imgColor;
String statusMessage;
if (isConnected) {
imgColor = "background-color: #007f00";
statusMessage = MSGS.connectionStatusConnected();
} else {
imgColor = "background-color: #eb3d00";
statusMessage = MSGS.connectionStatusDisconnected();
}
StringBuilder imageSB = new StringBuilder();
imageSB.append("<i class=\"fa fa-plug fa-fw\" ");
imageSB.append(
"style=\"float: right; width: 23px; height: 23px; line-height: 23px; color: white; border-radius: 23px; ");
imageSB.append(imgColor + "\"");
imageSB.append("\" title=\"");
imageSB.append(statusMessage);
imageSB.append("\"/>");
String html = this.status.getHTML();
String baseStatusHTML = html.substring(0, html.indexOf("Status") + "Status".length());
StringBuilder statusHTML = new StringBuilder(baseStatusHTML);
statusHTML.append(imageSB.toString());
this.status.setHTML(statusHTML.toString());
}
// create the prompt for dirty configuration before switching to another tab
private void renderDirtyConfigModal(Button b) {
if (this.servicesUi != null) {
this.servicesDirty = this.servicesUi.isDirty();
}
if (this.network.isVisible()) {
this.networkDirty = this.networkBinder.isDirty();
} else {
this.networkDirty = false;
}
if (this.firewall.isVisible()) {
this.firewallDirty = this.firewallBinder.isDirty();
} else {
this.firewallDirty = false;
}
if (this.settings.isVisible()) {
this.settingsDirty = this.settingsBinder.isDirty();
}
if (this.cloudServices.isVisible()) {
this.cloudServicesDirty = this.cloudServicesBinder.isDirty();
}
if (this.servicesUi != null && this.servicesUi.isDirty() || this.networkDirty || this.firewallDirty
|| this.settingsDirty || this.cloudServicesDirty) {
this.modal = new Modal();
ModalHeader header = new ModalHeader();
header.setTitle(MSGS.warning());
this.modal.add(header);
ModalBody body = new ModalBody();
body.add(new Span(MSGS.deviceConfigDirty()));
this.modal.add(body);
ModalFooter footer = new ModalFooter();
footer.add(b);
footer.add(new Button(MSGS.noButton(), new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
EntryClassUi.this.modal.hide();
}
}));
this.modal.add(footer);
this.modal.show();
} else {
b.click();
}
}
public boolean isNetworkDirty() {
if (this.network.isVisible()) {
return this.networkBinder.isDirty();
} else {
return false;
}
}
public boolean isFirewallDirty() {
if (this.firewall.isVisible()) {
return this.firewallBinder.isDirty();
} else {
return false;
}
}
public boolean isSettingsDirty() {
if (this.settings.isVisible()) {
return this.settingsBinder.isDirty();
} else {
return false;
}
}
public void setDirty(boolean b) {
if (this.servicesUi != null) {
this.servicesUi.setDirty(false);
}
if (this.network.isVisible()) {
this.networkBinder.setDirty(false);
}
if (this.firewall.isVisible()) {
this.firewallBinder.setDirty(false);
}
if (this.settings.isVisible()) {
this.settingsBinder.setDirty(false);
}
}
public static void showWaitModal() {
m_waitModal = new PopupPanel(false, true);
Icon icon = new Icon();
icon.setType(IconType.COG);
icon.setSize(IconSize.TIMES4);
icon.setSpin(true);
m_waitModal.setWidget(icon);
m_waitModal.setGlassEnabled(true);
m_waitModal.center();
m_waitModal.show();
}
public static void hideWaitModal() {
if (m_waitModal != null) {
m_waitModal.hide();
}
}
private void forceTabsCleaning() {
if (this.servicesUi != null) {
this.servicesUi.setDirty(false);
}
if (this.network.isVisible()) {
this.networkBinder.setDirty(false);
}
if (this.firewall.isVisible()) {
this.firewallBinder.setDirty(false);
}
if (this.settings.isVisible()) {
this.settingsBinder.setDirty(false);
}
if (this.cloudServices.isVisible()) {
this.cloudServicesBinder.setDirty(false);
}
}
private void eclipseMarketplaceInstall(String url) {
// Construct the REST URL for Eclipse Marketplace
String appId = url.split("=")[1];
final String empApi = "http://marketplace.eclipse.org/node/" + appId + "/api/p";
// Generate security token
EntryClassUi.showWaitModal();
this.gwtXSRFService.generateSecurityToken(new AsyncCallback<GwtXSRFToken>() {
@Override
public void onFailure(Throwable ex) {
EntryClassUi.hideWaitModal();
FailureHandler.handle(ex, EntryClassUi.class.getName());
}
@Override
public void onSuccess(GwtXSRFToken token) {
// Retrieve the URL of the DP via the Eclipse Marketplace API
EntryClassUi.this.gwtPackageService.getMarketplaceUri(token, empApi, new AsyncCallback<String>() {
@Override
public void onFailure(Throwable ex) {
EntryClassUi.hideWaitModal();
logger.log(Level.SEVERE, ex.getMessage(), ex);
FailureHandler.handle(ex, EntryClassUi.class.getName());
}
@Override
public void onSuccess(String result) {
installMarketplaceDp(result);
Timer timer = new Timer() {
@Override
public void run() {
initServicesTree();
EntryClassUi.hideWaitModal();
}
};
timer.schedule(2000);
}
});
}
});
}
private void installMarketplaceDp(final String uri) {
String url = "/" + GWT.getModuleName() + "/file/deploy/url";
final RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, URL.encode(url));
this.gwtXSRFService.generateSecurityToken(new AsyncCallback<GwtXSRFToken>() {
@Override
public void onFailure(Throwable ex) {
EntryClassUi.hideWaitModal();
FailureHandler.handle(ex, EntryClassUi.class.getName());
}
@Override
public void onSuccess(GwtXSRFToken token) {
StringBuilder sb = new StringBuilder();
sb.append("xsrfToken=" + token.getToken());
sb.append("&packageUrl=" + uri);
builder.setHeader("Content-type", "application/x-www-form-urlencoded");
try {
builder.sendRequest(sb.toString(), new RequestCallback() {
@Override
public void onResponseReceived(Request request, Response response) {
logger.info(response.getText());
}
@Override
public void onError(Request request, Throwable ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
FailureHandler.handle(ex, EntryClassUi.class.getName());
}
});
} catch (RequestException e) {
logger.log(Level.SEVERE, e.getMessage(), e);
FailureHandler.handle(e, EntryClassUi.class.getName());
}
}
});
}
public static native void dragDropInit(EntryClassUi ecu) /*-{
$wnd.$("html").on("dragover", function(event) {
event.preventDefault();
event.stopPropagation();
});
$wnd.$("html").on("dragleave", function(event) {
event.preventDefault();
event.stopPropagation();
});
$wnd.$("html").on("drop", function(event) {
event.preventDefault();
event.stopPropagation();
console.log(event.originalEvent.dataTransfer.getData("text"));
if (confirm("Install file?") == true) {
ecu.@org.eclipse.kura.web.client.ui.EntryClassUi::eclipseMarketplaceInstall(Ljava/lang/String;)(event.originalEvent.dataTransfer.getData("text"));
}
});
}-*/;
}