package org.activityinfo.ui.client.page.report;
/*
* #%L
* ActivityInfo Server
* %%
* Copyright (C) 2009 - 2013 UNICEF
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.core.El;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MessageBoxEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.widget.Dialog;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.ProgressBar;
import com.extjs.gxt.ui.client.widget.Text;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.layout.VBoxLayout;
import com.extjs.gxt.ui.client.widget.layout.VBoxLayout.VBoxLayoutAlign;
import com.extjs.gxt.ui.client.widget.layout.VBoxLayoutData;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.http.client.*;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.RootPanel;
import org.activityinfo.i18n.shared.I18N;
import org.activityinfo.legacy.client.Dispatcher;
import org.activityinfo.legacy.shared.command.Filter;
import org.activityinfo.legacy.shared.command.FilterUrlSerializer;
import org.activityinfo.legacy.shared.command.RenderElement;
import org.activityinfo.legacy.shared.command.RenderElement.Format;
import org.activityinfo.legacy.shared.command.result.UrlResult;
import org.activityinfo.legacy.shared.reports.model.ReportElement;
import org.activityinfo.promise.Promise;
public class ExportDialog extends Dialog {
private final Dispatcher dispatcher;
private ProgressBar bar;
private Text downloadLink;
private boolean canceled = false;
private Button button;
public ExportDialog(Dispatcher dispatcher) {
this.dispatcher = dispatcher;
setWidth(350);
setHeight(175);
setHeadingText(I18N.CONSTANTS.export());
setClosable(false);
setButtonAlign(HorizontalAlignment.CENTER);
VBoxLayout layout = new VBoxLayout();
layout.setVBoxLayoutAlign(VBoxLayoutAlign.LEFT);
setLayout(layout);
bar = new ProgressBar();
bar.setWidth(300);
add(bar, new VBoxLayoutData(new Margins(20, 15, 25, 15)));
downloadLink = new Text(I18N.CONSTANTS.clickToDownload());
downloadLink.setTagName("a");
downloadLink.setVisible(false);
add(downloadLink, new VBoxLayoutData(0, 15, 0, 15));
}
@Override
protected void createButtons() {
button = new Button();
button.setText(I18N.CONSTANTS.cancel());
button.addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent ce) {
ExportDialog.this.canceled = true;
bar.reset();
hide();
}
});
getButtonBar().add(button);
}
public void export(String filename, ReportElement model, Format format) {
showStartProgress();
RenderElement command = new RenderElement(model, format);
command.setFilename(filename);
dispatcher.execute(command, new AsyncCallback<UrlResult>() {
@Override
public void onFailure(Throwable caught) {
showError();
}
@Override
public void onSuccess(UrlResult result) {
if (!canceled) {
initiateDownload(result.getUrl());
}
}
});
}
private void showStartProgress() {
show();
bar.updateText(I18N.CONSTANTS.exportProgress());
bar.auto();
}
private void showError() {
MessageBox.alert(I18N.CONSTANTS.export(), I18N.CONSTANTS.serverError(), new Listener<MessageBoxEvent>() {
@Override
public void handleEvent(MessageBoxEvent be) {
ExportDialog.this.hide();
}
});
}
private void initiateDownload(String url) {
bar.reset();
bar.updateProgress(1.0, I18N.CONSTANTS.downloadReady());
button.setText(I18N.CONSTANTS.close());
tryStartDownloadWithIframe(url);
downloadLink.getElement().setAttribute("href", url);
downloadLink.setVisible(true);
layout(true);
}
public void exportSites(Filter filter) {
showStartProgress();
RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.POST, "/ActivityInfo/export");
requestBuilder.setHeader("Content-type", "application/x-www-form-urlencoded");
requestBuilder.setRequestData("filter=" + FilterUrlSerializer.toUrlFragment(filter));
requestBuilder.setCallback(new RequestCallback() {
@Override
public void onResponseReceived(Request request, Response response) {
final String exportId = response.getText();
getDownloadUrl(exportId).then(new AsyncCallback<String>() {
@Override
public void onFailure(Throwable caught) {
showError();
}
@Override
public void onSuccess(String downloadUrl) {
initiateDownload(downloadUrl);
}
});
}
@Override
public void onError(Request request, Throwable exception) {
showError();
}
});
try {
requestBuilder.send();
} catch (RequestException e) {
showError();
}
}
private Promise<String> getDownloadUrl(String exportId) {
final Promise<String> url = new Promise<>();
schedulePoll(exportId, url);
return url;
}
private void schedulePoll(final String exportId, final Promise<String> downloadUrl) {
Scheduler.get().scheduleFixedDelay(new Scheduler.RepeatingCommand() {
@Override
public boolean execute() {
pollServer(exportId, downloadUrl);
return false;
}
}, 1000);
}
private void pollServer(final String exportId, final Promise<String> downloadUrl) {
RequestBuilder request = new RequestBuilder(RequestBuilder.GET, "/ActivityInfo/export?id=" + exportId);
request.setCallback(new RequestCallback() {
@Override
public void onResponseReceived(Request request, Response response) {
if(response.getStatusCode() == 200) {
downloadUrl.onSuccess(response.getText());
} else {
schedulePoll(exportId, downloadUrl);
}
}
@Override
public void onError(Request request, Throwable exception) {
downloadUrl.onFailure(exception);
}
});
try {
request.send();
} catch (RequestException e) {
downloadUrl.onFailure(e);
}
}
private void tryStartDownloadWithIframe(String url) {
com.google.gwt.user.client.ui.Frame frame = new com.google.gwt.user.client.ui.Frame(url);
El el = El.fly(frame.getElement());
el.setStyleAttribute("width", 0);
el.setStyleAttribute("height", 0);
el.setStyleAttribute("position", "absolute");
el.setStyleAttribute("border", 0);
RootPanel.get().add(frame);
}
}