diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/Headerbar.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/Headerbar.java index 8e04fd3..5f18579 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/Headerbar.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/Headerbar.java @@ -185,13 +185,7 @@ public class Headerbar extends Composite{ presenter.updateWorkflowDocument(false); } }; - - Command showChanges = new Command() { - public void execute() { - presenter.showLastChangesPopup(); - } - }; - + if (canUpdate) workflowMenu.addItem("Update this document", updateWfDocument); //workflowMenu.addItem("Show previous changes", showChanges); @@ -454,47 +448,8 @@ public class Headerbar extends Composite{ */ private MenuItem getFileMenu() { - Command newTemplate = new Command() { - public void execute() { - presenter.changeTemplateName(TemplateModel.DEFAULT_NAME); - presenter.cleanAll(); - } - }; - Command openTemplate = new Command() { - public void execute() { - GWT.runAsync(WorkspaceLightTreeLoadPopup.class, new RunAsyncCallback() { - public void onSuccess() { - - int left = mainLayout.getAbsoluteLeft() + 50; - int top = mainLayout.getAbsoluteTop() + 25; - - WorkspaceLightTreeLoadPopup wpTreepopup = new WorkspaceLightTreeLoadPopup("Open Template", true, true); - wpTreepopup.setShowableTypes(ItemType.REPORT_TEMPLATE); - wpTreepopup.setSelectableTypes(ItemType.REPORT_TEMPLATE); - - wpTreepopup.addPopupHandler(new PopupHandler() { - public void onPopup(PopupEvent event) { - if (! event.isCanceled()) { - if (event.getSelectedItem() != null) { - presenter.openTemplate(event.getSelectedItem().getName(), event.getSelectedItem().getId(), true); - } - presenter.getHeader().enableExports(); - } - } - }); - wpTreepopup.setPopupPosition(left, top); - wpTreepopup.show(); - } - - public void onFailure(Throwable reason) { - Window.alert("There are networks problem, please check your connection."); - } - }); - - - - } - }; + CommonCommands cmd = new CommonCommands(presenter); + Command openHelp = new Command() { @@ -518,38 +473,7 @@ public class Headerbar extends Composite{ }; - Command openReport = new Command() { - public void execute() { - - GWT.runAsync(WorkspaceLightTreeLoadPopup.class, new RunAsyncCallback() { - public void onSuccess() { - int left = mainLayout.getAbsoluteLeft() + 50; - int top = mainLayout.getAbsoluteTop() + 25; - - WorkspaceLightTreeLoadPopup wpTreepopup = new WorkspaceLightTreeLoadPopup("Open Report", true, true); - wpTreepopup.setShowableTypes(ItemType.REPORT); - wpTreepopup.setSelectableTypes(ItemType.REPORT); - wpTreepopup.addPopupHandler(new PopupHandler() { - public void onPopup(PopupEvent event) { - if (! event.isCanceled()) { - if (event.getSelectedItem() != null) { - presenter.openTemplate(event.getSelectedItem().getName(), event.getSelectedItem().getId(), false); - } - presenter.getHeader().enableExports(); - } - - } - }); - wpTreepopup.setPopupPosition(left, top); - wpTreepopup.show(); - } - - public void onFailure(Throwable reason) { - Window.alert("There are networks problem, please check your connection."); - } - }); - } - }; + Command saveReportAs = new Command() { public void execute() { @@ -579,14 +503,14 @@ public class Headerbar extends Composite{ fileMenu.setAnimationEnabled(true); MenuItem toReturn = new MenuItem("File", fileMenu); - fileMenu.addItem("Open Report", openReport); - fileMenu.addItem("Open template...", openTemplate); + fileMenu.addItem("Open Report", cmd.openReport); + fileMenu.addItem("Open template...", cmd.openTemplate); fileMenu.addSeparator(); fileMenu.addItem("Save", saveReport); fileMenu.addItem("Save As ..", saveReportAs); fileMenu.addSeparator(); // fileMenu.addItem("Import from FiMES XML", importFimes); - fileMenu.addItem("Close Report", newTemplate); + fileMenu.addItem("Close Report", cmd.newTemplate); fileMenu.addSeparator(); fileMenu.addItem("? Open User's Guide", openHelp); return toReturn; diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/Presenter/CommonCommands.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/Presenter/CommonCommands.java index 807fa34..5f4e423 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/Presenter/CommonCommands.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/Presenter/CommonCommands.java @@ -2,6 +2,7 @@ package org.gcube.portlets.user.reportgenerator.client.Presenter; import org.gcube.portlets.user.reportgenerator.client.ReportConstants; import org.gcube.portlets.user.reportgenerator.client.dialog.ImporterDialog; +import org.gcube.portlets.user.reportgenerator.client.model.TemplateModel; import org.gcube.portlets.user.workspace.lighttree.client.ItemType; import org.gcube.portlets.user.workspace.lighttree.client.event.PopupEvent; import org.gcube.portlets.user.workspace.lighttree.client.event.PopupHandler; @@ -36,6 +37,8 @@ public class CommonCommands { * */ public Command openReport; + + public Command newTemplate; /** * */ @@ -61,6 +64,16 @@ public class CommonCommands { */ public CommonCommands(final Presenter presenter) { this.presenter = presenter; + + newTemplate = new Command() { + public void execute() { + presenter.changeTemplateName(TemplateModel.DEFAULT_NAME); + presenter.cleanAll(); + presenter.showOpenOptions(); + } + }; + + openTemplate = new Command() { public void execute() { final int left = presenter.getHeader().getMainLayout().getAbsoluteLeft() + 50; @@ -69,6 +82,7 @@ public class CommonCommands { GWT.runAsync(WorkspaceLightTreeLoadPopup.class, new RunAsyncCallback() { public void onSuccess() { WorkspaceLightTreeLoadPopup wpTreepopup = new WorkspaceLightTreeLoadPopup("Select a Template to open", true, true); + wpTreepopup.setWidth("450px"); wpTreepopup.setShowableTypes(ItemType.REPORT_TEMPLATE); wpTreepopup.setSelectableTypes(ItemType.REPORT_TEMPLATE); @@ -104,6 +118,7 @@ public class CommonCommands { int top = presenter.getHeader().getMainLayout().getAbsoluteTop() + 25; WorkspaceLightTreeLoadPopup wpTreepopup = new WorkspaceLightTreeLoadPopup("Select a Report to open", true, true); + wpTreepopup.setWidth("450px"); wpTreepopup.setShowableTypes(ItemType.REPORT); wpTreepopup.setSelectableTypes(ItemType.REPORT); wpTreepopup.addPopupHandler(new PopupHandler() { @@ -166,7 +181,7 @@ public class CommonCommands { public void onSuccess() { WorkspaceLightTreeLoadPopup wpTreepopup = new WorkspaceLightTreeLoadPopup("Pick the item you want to import from", true, true); wpTreepopup.setShowableTypes(ItemType.REPORT_TEMPLATE); - + wpTreepopup.setWidth("450px"); wpTreepopup.addPopupHandler(new PopupHandler() { public void onPopup(PopupEvent event) { @@ -216,6 +231,7 @@ public class CommonCommands { GWT.runAsync(WorkspaceLightTreeSavePopup.class, new RunAsyncCallback() { public void onSuccess() { WorkspaceLightTreeSavePopup wpTreepopup = new WorkspaceLightTreeSavePopup("Save Template, choose folder please:", true); + wpTreepopup.setWidth("450px"); wpTreepopup.setSelectableTypes( ItemType.FOLDER, ItemType.ROOT); wpTreepopup.setShowEmptyFolders(true); diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/Presenter/Presenter.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/Presenter/Presenter.java index 098a675..41e792f 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/Presenter/Presenter.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/Presenter/Presenter.java @@ -8,7 +8,6 @@ import org.gcube.portlets.d4sreporting.common.shared.ComponentType; import org.gcube.portlets.d4sreporting.common.shared.Metadata; import org.gcube.portlets.d4sreporting.common.shared.Model; import org.gcube.portlets.user.exporter.client.ReportExporterPopup; -import org.gcube.portlets.user.exporter.client.ReportExporterServiceAsync; import org.gcube.portlets.user.exporter.client.event.ExportingCompletedEvent; import org.gcube.portlets.user.exporter.client.event.ExportingCompletedEventHandler; import org.gcube.portlets.user.exporter.client.event.ReportExporterEvent; @@ -257,9 +256,9 @@ public class Presenter { commonCommands = new CommonCommands(this); //importDlg = new FimesFileUploadWindow(eventBus); } - - public void showLastChangesPopup() { - + + public void showOpenOptions() { + wp.showOpenOptions(); } public void showSectionUserCommentsTooltips() { @@ -351,15 +350,8 @@ public class Presenter { */ HashMap toReturn = new HashMap(); - Command newTemplate= new Command() { - public void execute() { - changeTemplateName(TemplateModel.DEFAULT_NAME); - cleanAll(); - } - }; - toReturn.put("save", commonCommands.saveTemplate); - toReturn.put("newdoc", newTemplate); + toReturn.put("newdoc", commonCommands.newTemplate); toReturn.put("open_report", commonCommands.openReport); toReturn.put("open_template", commonCommands.openTemplate); toReturn.put("importing", commonCommands.importTemplateCommand); @@ -441,27 +433,15 @@ public class Presenter { //persists the change in the session model.storeInSession(); } - /** - * just clean the page + * remove the user-added components from the workspace (in the current page) but not from the model + * */ - public void cleanAllNotSession() { - // reset the model - model = new TemplateModel(this); - - //reset the UI - - //give the new model instance - header.setModel(model); - wp.setModel(model); - - cleanWorkspace(); - titleBar.hideNextButton(); - titleBar.hidePrevButton(); - titleBar.setTemplateName(model.getTemplateName()); - titleBar.setPageDisplayer(model.getCurrentPage(), model.getTotalPages()); - resizeWorkingArea(model.getPageWidth(), model.getPageHeight()); + public void cleanWorkspace() { + wp.getMainLayout().clear(); + ReportGenerator.get().getScrollerPanel().setScrollPosition(0); } + /** * Save the current report @@ -501,14 +481,7 @@ public class Presenter { titleBar.setTemplateName(templateName); } - /** - * remove the user-added components from the workspace (in the current page) but not from the model - * - */ - public void cleanWorkspace() { - wp.getMainLayout().clear(); - ReportGenerator.get().getScrollerPanel().setScrollPosition(0); - } + /** * @@ -746,27 +719,21 @@ public class Presenter { * @param isTemplate true if you are opening a template false if you are opening a report */ public void openTemplate(String templateToOpen, String templateObjectID, final boolean isTemplate) { - AsyncCallback callback = new AsyncCallback() { - + //will asyncrously return a Serializable Model instance read from disk + model.getModelService().readModel(templateToOpen, templateObjectID, isTemplate, false, new AsyncCallback() { + @Override + public void onSuccess(Model toLoad) { + if (toLoad != null) + loadModel(toLoad); + else + Window.alert("Could not Load template, error on server: "); + } + @Override public void onFailure(Throwable caught) { Window.alert("Could not Load template, please try again later: " + caught.getMessage()); } - - public void onSuccess(Model toLoad) { - if (toLoad.getPageWidth() == TemplateModel.OLD_TEMPLATE_WIDTH) { - if (isTemplate) - Window.alert("OPS! we think you are trying to open a previuos version template, only gCube Templates 1.5+ are supported"); - else - Window.alert("OPS! we think you are trying to open a previuos version Report, only gCube Reports 1.5+ are supported"); - } - else - loadModel(toLoad); - } - }; - - //will asyncrously return a SerializableModel instance read from disk - model.getModelService().readModel(templateToOpen, templateObjectID, isTemplate, false, callback); + }); } /** * load the template to edit in the MODEL and in the VIEW @@ -774,12 +741,14 @@ public class Presenter { */ public void openImportedFimesXML(String serializedpath) { model.getModelService().readImportedModel(serializedpath, new AsyncCallback() { - public void onFailure(Throwable caught) { - Window.alert("Could not Load report, please try again later: " + caught.getMessage()); - } + @Override public void onSuccess(Model toLoad) { loadModel(toLoad); } + @Override + public void onFailure(Throwable caught) { + Window.alert("Could not Load report, please try again later: " + caught.getMessage()); + } }); } @@ -812,7 +781,27 @@ public class Presenter { } if (currPage > 1) titleBar.showPrevButton(); + } + + /** + * just clean the page + */ + public void cleanAllNotSession() { + // reset the model + model = new TemplateModel(this); + //reset the UI + + //give the new model instance + header.setModel(model); + wp.setModel(model); + + cleanWorkspace(); + titleBar.hideNextButton(); + titleBar.hidePrevButton(); + titleBar.setTemplateName(model.getTemplateName()); + titleBar.setPageDisplayer(model.getCurrentPage(), model.getTotalPages()); + resizeWorkingArea(model.getPageWidth(), model.getPageHeight()); } private void loadFirstSection() { diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportGenerator.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportGenerator.java index 83cf59e..ac87873 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportGenerator.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportGenerator.java @@ -16,6 +16,7 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.RunAsyncCallback; import com.google.gwt.event.logical.shared.ResizeEvent; import com.google.gwt.event.logical.shared.ResizeHandler; +import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.CellPanel; import com.google.gwt.user.client.ui.HTML; @@ -169,8 +170,7 @@ public class ReportGenerator implements EntryPoint { } } - }); - + }); //presenter.showExportPanel("", "", null, ""); //showGuidedTour() ; diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportService.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportService.java index 4cb8f2f..af67937 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportService.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportService.java @@ -81,4 +81,6 @@ public interface ReportService extends RemoteService{ * @return */ Model readImportedModel(String tempPath); + + void renewHTTPSession(); } diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportServiceAsync.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportServiceAsync.java index b51b6fc..45fa4ab 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportServiceAsync.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportServiceAsync.java @@ -75,4 +75,5 @@ public interface ReportServiceAsync { AsyncCallback callback); void save(String filePath, String workspaceFolderId, String ItemName, TypeExporter type, boolean overwrite, AsyncCallback callback); + void renewHTTPSession(AsyncCallback callback); } diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/WorkspacePanel.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/WorkspacePanel.java index 036d4aa..0092ca2 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/WorkspacePanel.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/WorkspacePanel.java @@ -5,6 +5,7 @@ package org.gcube.portlets.user.reportgenerator.client; import org.gcube.portlets.user.reportgenerator.client.Presenter.Presenter; import org.gcube.portlets.user.reportgenerator.client.model.TemplateModel; import org.gcube.portlets.user.reportgenerator.client.targets.DoubleColumnPanel; +import org.gcube.portlets.user.reportgenerator.client.uibinder.OpenOptions; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; @@ -66,13 +67,14 @@ public class WorkspacePanel extends Composite { templateModel = presenter.getModel(); mainLayout.setWidth(""+(templateModel.getPageWidth())); - mainLayout.setStyleName("wpFlow"); - - + mainLayout.setStyleName("wpFlow"); - initWidget(mainLayout); - + initWidget(mainLayout); + showOpenOptions(); + } + public void showOpenOptions() { + mainLayout.add(new OpenOptions(presenter)); } /** diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/model/TemplateModel.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/model/TemplateModel.java index b81ada4..b46776d 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/model/TemplateModel.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/model/TemplateModel.java @@ -19,6 +19,7 @@ import org.gcube.portlets.user.reportgenerator.client.Presenter.Presenter; import com.extjs.gxt.ui.client.widget.MessageBox; import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget; @@ -157,6 +158,20 @@ public class TemplateModel { this.presenter = presenter; String moduleRelativeURL = GWT.getModuleBaseURL() + "ReportServiceImpl"; endpoint.setServiceEntryPoint(moduleRelativeURL); + + Timer renewSessionTimer = new Timer() { + + @Override + public void run() { + modelService.renewHTTPSession(new AsyncCallback() { + @Override + public void onFailure(Throwable caught) {} + @Override + public void onSuccess(Void result) {} + }); + } + }; + renewSessionTimer.scheduleRepeating(1000*60*30); // renew session every 30 minutes } /** @@ -307,7 +322,7 @@ public class TemplateModel { /** - * generally used when reaing a model form disk + * generally used when reading a model form disk * @param toLoad the SerializableModel instance where toget the section * @param sectionNoToimport section to import 0 -> n-1 * @param beforeSection say where to import this section (before) diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/OpenOptions.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/OpenOptions.java new file mode 100644 index 0000000..e23d2ff --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/OpenOptions.java @@ -0,0 +1,77 @@ +package org.gcube.portlets.user.reportgenerator.client.uibinder; + +import org.gcube.portlets.user.reportgenerator.client.Presenter.CommonCommands; +import org.gcube.portlets.user.reportgenerator.client.Presenter.Presenter; +import org.gcube.portlets.user.reportgenerator.client.uibinder.ExportOptions.ExportMode; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.uibinder.client.UiHandler; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.HTMLPanel; +import com.google.gwt.user.client.ui.Widget; + +public class OpenOptions extends Composite { + + private static OpenOptionsUiBinder uiBinder = GWT + .create(OpenOptionsUiBinder.class); + + interface OpenOptionsUiBinder extends UiBinder { + } + enum OpenMode {OPEN_REPORT, OPEN_TEMPLATE, UPLOAD } + + @UiField HTML openReport; + @UiField HTML openTemplate; + @UiField HTML uploadReport; + + @UiField HTMLPanel myPanel; + + private Presenter p; + + public OpenOptions(Presenter p) { + initWidget(uiBinder.createAndBindUi(this)); + this.p = p; + } + + public HTMLPanel getMainPanel() { + return myPanel; + } + @UiHandler("openReport") + void onOpenReportClick(ClickEvent e) { + GWT.log("openReport"); + doAction(OpenMode.OPEN_REPORT); + } + + @UiHandler("openTemplate") + void onOpenTemplateClick(ClickEvent e) { + GWT.log("openTemplate"); + doAction(OpenMode.OPEN_TEMPLATE); + } + + @UiHandler("uploadReport") + void unUploadClick(ClickEvent e) { + doAction(OpenMode.UPLOAD); + } + + private void doAction(OpenMode mode) { + CommonCommands cmd = new CommonCommands(p); + switch (mode) { + case OPEN_REPORT: + cmd.openReport.execute(); + break; + case OPEN_TEMPLATE: + cmd.openTemplate.execute(); + break; + case UPLOAD: + + break; + default: + break; + } + + } +} diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/OpenOptions.ui.xml b/src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/OpenOptions.ui.xml new file mode 100644 index 0000000..b066d9a --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/OpenOptions.ui.xml @@ -0,0 +1,19 @@ + + + + + + + + + +
+ Load Template + + Open/Edit Report + + Upload from Desktop +
+
+
\ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/server/servlet/ReportServiceImpl.java b/src/main/java/org/gcube/portlets/user/reportgenerator/server/servlet/ReportServiceImpl.java index aa0d000..22da619 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/server/servlet/ReportServiceImpl.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/server/servlet/ReportServiceImpl.java @@ -1646,7 +1646,9 @@ public class ReportServiceImpl extends RemoteServiceServlet implements ReportSe } } - - - + @Override + public void renewHTTPSession() { + HttpSession session = this.getThreadLocalRequest().getSession(); + _log.info("HTTP Session renewed" + new Date(session.getLastAccessedTime())); + } } diff --git a/src/main/webapp/ReportGenerator.css b/src/main/webapp/ReportGenerator.css index 2bea911..88e2ae3 100644 --- a/src/main/webapp/ReportGenerator.css +++ b/src/main/webapp/ReportGenerator.css @@ -1,5 +1,42 @@ @import url('reports/old-dialog.css'); + +.openOptionsPanel { + margin: 25px 5px 0px -45px; + border: 1px solid #e3e8f3; + padding: 5px; +} + +.openOption { + display: block; + height: 160px; + width: 250px; + opacity: 0.8; + text-align: center; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 18px; + color: #444; +} + +.openOption:hover { + cursor: pointer; + cursor: hand; + opacity: 1.0; +} + +.optionOpenReport { + background: url('images/openReport.png') 50% 25px no-repeat; +} + +.optionOpenTemplate { + background: url('images/openTemplate.png') 50% 25px no-repeat; +} + +.optionUpload { + background: url('images/uploadReport.png') 55% 25px no-repeat; +} + + .exportPanel { margin: 5px 5px 5px 20px; border: 1px solid #e3e8f3; diff --git a/src/main/webapp/images/openReport.png b/src/main/webapp/images/openReport.png new file mode 100644 index 0000000..fe3aebe Binary files /dev/null and b/src/main/webapp/images/openReport.png differ diff --git a/src/main/webapp/images/openTemplate.png b/src/main/webapp/images/openTemplate.png new file mode 100644 index 0000000..726c4bc Binary files /dev/null and b/src/main/webapp/images/openTemplate.png differ diff --git a/src/main/webapp/images/uploadReport.png b/src/main/webapp/images/uploadReport.png new file mode 100644 index 0000000..c43e53e Binary files /dev/null and b/src/main/webapp/images/uploadReport.png differ