From 9adc51f0ef28f7cd4a0af72662857f6492374846 Mon Sep 17 00:00:00 2001 From: Massimiliano Assante Date: Fri, 15 Mar 2013 18:06:43 +0000 Subject: [PATCH] almost warking exports git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/user/reports@71449 82a268e6-3cf1-43bd-a215-b396298e98cf --- .settings/org.eclipse.wst.common.component | 3 + .../client/Presenter/Presenter.java | 60 +++++++++---- .../client/ReportGenerator.java | 11 ++- .../reportgenerator/client/ReportService.java | 13 ++- .../client/ReportServiceAsync.java | 7 +- .../client/WorkspacePanel.java | 2 +- .../client/uibinder/ExportOptions.java | 84 ++++++++++++++++++ .../client/uibinder/ExportOptions.ui.xml | 25 ++++++ .../server/servlet/ReportServiceImpl.java | 44 +++++++++ .../shared/ReportExporterException.java | 25 ++++++ .../shared/SaveReportFileException.java | 16 ++++ .../shared/SaveReportFileExistException.java | 18 ++++ src/main/webapp/ReportGenerator.css | 46 ++++++++++ src/main/webapp/images/save.png | Bin 0 -> 5768 bytes src/main/webapp/images/save_as.png | Bin 0 -> 7319 bytes src/main/webapp/images/save_open.png | Bin 0 -> 7780 bytes 16 files changed, 324 insertions(+), 30 deletions(-) create mode 100644 src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/ExportOptions.java create mode 100644 src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/ExportOptions.ui.xml create mode 100644 src/main/java/org/gcube/portlets/user/reportgenerator/shared/ReportExporterException.java create mode 100644 src/main/java/org/gcube/portlets/user/reportgenerator/shared/SaveReportFileException.java create mode 100644 src/main/java/org/gcube/portlets/user/reportgenerator/shared/SaveReportFileExistException.java create mode 100644 src/main/webapp/images/save.png create mode 100644 src/main/webapp/images/save_as.png create mode 100644 src/main/webapp/images/save_open.png diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 2dc054b..0dde3da 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -5,6 +5,9 @@ + + uses + 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 49b4c61..9257f01 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,11 +8,16 @@ 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; import org.gcube.portlets.user.exporter.client.event.ReportExporterEventHandler; import org.gcube.portlets.user.exporter.shared.TypeExporter; import org.gcube.portlets.user.reportgenerator.client.Headerbar; import org.gcube.portlets.user.reportgenerator.client.ReportGenerator; +import org.gcube.portlets.user.reportgenerator.client.ReportService; +import org.gcube.portlets.user.reportgenerator.client.ReportServiceAsync; import org.gcube.portlets.user.reportgenerator.client.TitleBar; import org.gcube.portlets.user.reportgenerator.client.ToolboxPanel; import org.gcube.portlets.user.reportgenerator.client.WorkspacePanel; @@ -46,6 +51,7 @@ import org.gcube.portlets.user.reportgenerator.client.targets.HeadingTextArea; import org.gcube.portlets.user.reportgenerator.client.targets.ReportTextArea; import org.gcube.portlets.user.reportgenerator.client.targets.TSArea; import org.gcube.portlets.user.reportgenerator.client.targets.TextTableImage; +import org.gcube.portlets.user.reportgenerator.client.uibinder.ExportOptions; import org.gcube.portlets.user.reportgenerator.shared.SessionInfo; import org.gcube.portlets.user.reportgenerator.shared.UserBean; @@ -53,14 +59,13 @@ import com.extjs.gxt.ui.client.widget.MessageBox; import com.extjs.gxt.ui.client.widget.layout.FitLayout; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.RunAsyncCallback; -import com.google.gwt.event.shared.EventBus; import com.google.gwt.event.shared.HandlerManager; -import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.user.client.Command; 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.ui.HTML; +import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.RichTextArea; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; @@ -74,6 +79,7 @@ import com.google.gwt.user.client.ui.Widget; */ public class Presenter { + private ReportServiceAsync reportService = (ReportServiceAsync) GWT.create(ReportService.class); /** * View part */ @@ -83,10 +89,9 @@ public class Presenter { private ToolboxPanel toolBoxPanel; -// private FimesFileUploadWindow importDlg; - private TitleBar titleBar; - + + private HorizontalPanel exportsPanel; private UserBean currentUser; private String currentScope; @@ -118,6 +123,14 @@ public class Presenter { private void handleEvents() { + + eventBus.addHandler(ExportingCompletedEvent.TYPE, new ExportingCompletedEventHandler() { + @Override + public void onExportFinished(ExportingCompletedEvent event) { + showExportSaveOptions(event.getFilePath(), event.getItemName(), event.getType()); + } + }); + eventBus.addHandler(AddBiblioEvent.TYPE, new AddBiblioEventHandler() { public void onAddCitation(AddBiblioEvent event) { addCitation(event.getCitekey(), event.getCitetext()); @@ -135,11 +148,6 @@ public class Presenter { } }); -// eventBus.addHandler(ExportFinishedEvent.TYPE, new EsportFinishedEventHandler() { -// public void onFinishedExport(ExportFinishedEvent event) { -// refreshWorkspace(); -// } -// }); eventBus.addHandler(ReportExporterEvent.TYPE, new ReportExporterEventHandler() { @Override @@ -432,15 +440,7 @@ public class Presenter { //persists the change in the session model.storeInSession(); } - /** - * when export is done this method is called - * @param filePath - * @param itemName - * @param type - */ - public void showExportSaveOptions(final String filePath, final String itemName, final TypeExporter type) { - - } + /** * just clean the page */ @@ -1131,5 +1131,27 @@ public class Presenter { } + public HorizontalPanel getExportsPanel() { + return exportsPanel; + } + + public void setExportsPanel(HorizontalPanel exportsPanel) { + this.exportsPanel = exportsPanel; + } + + /** + * when export is done this method is called + * @param filePath + * @param itemName + * @param type + */ + public void showExportSaveOptions(final String filePath, final String itemName, final TypeExporter type) { + ExportOptions exo = new ExportOptions(this, toolBoxPanel, filePath, itemName, type, reportService); + exportsPanel.add(exo); + } + + public void clearExportPanel() { + exportsPanel.clear(); + } } 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 2b0481f..62506cf 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 @@ -1,5 +1,6 @@ package org.gcube.portlets.user.reportgenerator.client; +import org.gcube.portlets.user.exporter.shared.TypeExporter; import org.gcube.portlets.user.guidedtour.client.GCUBEGuidedTour; import org.gcube.portlets.user.guidedtour.client.steps.GCUBETemplate1Text1Image; import org.gcube.portlets.user.guidedtour.client.steps.GCUBETemplate2Text2Image; @@ -34,11 +35,10 @@ import com.google.gwt.user.client.ui.VerticalPanel; * Entry point classes define onModuleLoad(). * * - * ReportGen class is the Entry point class, defines the main layout of the UI + * ReportGeneretor class is the Entry point class, defines the main layout of the UI * * @author Massimiliano Assante, ISTI-CNR - massimiliano.assante@isti.cnr.it - * - * @version June 2011 (3.0) + */ public class ReportGenerator implements EntryPoint { @@ -86,6 +86,8 @@ public class ReportGenerator implements EntryPoint { private TitleBar titlebar; + private HorizontalPanel exportResultsPanel = new HorizontalPanel(); + private WorkspacePanel workSpacePanel; private VerticalPanel eastPanel = new VerticalPanel(); @@ -116,6 +118,7 @@ public class ReportGenerator implements EntryPoint { presenter.setTitleBar(titlebar); presenter.setWp(workSpacePanel); presenter.setToolBoxPanel(toolBoxPanel); + presenter.setExportsPanel(exportResultsPanel); mainLayout.add(titlebar); mainLayout.add(header); @@ -140,6 +143,7 @@ public class ReportGenerator implements EntryPoint { divHidden.addStyleName("hasRichTextToolbar"); divHidden.addStyleName("setVisibilityOff"); + eastPanel.add(exportResultsPanel); eastPanel.add(workSpacePanel); eastPanel.add(divHidden); bottomScrollerPanel.add(eastPanel); @@ -174,6 +178,7 @@ public class ReportGenerator implements EntryPoint { }); //showGuidedTour() ; + //presenter.showExportSaveOptions("", "", TypeExporter.DOCX, null); } private void 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 fdf91ff..4cb8f2f 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 @@ -1,19 +1,24 @@ package org.gcube.portlets.user.reportgenerator.client; import org.gcube.portlets.d4sreporting.common.shared.Model; -import org.gcube.portlets.d4sreporting.common.shared.Table; import org.gcube.portlets.d4sreporting.common.shared.RepTimeSeries; -import org.gcube.portlets.user.reportgenerator.client.model.ExportManifestationType; +import org.gcube.portlets.d4sreporting.common.shared.Table; +import org.gcube.portlets.user.exporter.shared.SaveReportFileException; +import org.gcube.portlets.user.exporter.shared.SaveReportFileExistException; +import org.gcube.portlets.user.exporter.shared.TypeExporter; import org.gcube.portlets.user.reportgenerator.shared.SessionInfo; import com.google.gwt.user.client.rpc.RemoteService; +import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; /** * Service interface for server communication * @author Massimiliano Assante, ISTI-CNR - massimiliano.assante@isti.cnr.it - * @version november 2008 (0.1) */ - +@RemoteServiceRelativePath("ReportServiceImpl") public interface ReportService extends RemoteService{ + String save(String filePath, String workspaceFolderId, String ItemName, + TypeExporter type, boolean overwrite) + throws SaveReportFileException, SaveReportFileExistException; /** * return the first ten records of the timeseries having id as param * @param sTS . 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 acea9bd..b51b6fc 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 @@ -1,9 +1,9 @@ package org.gcube.portlets.user.reportgenerator.client; import org.gcube.portlets.d4sreporting.common.shared.Model; -import org.gcube.portlets.d4sreporting.common.shared.Table; import org.gcube.portlets.d4sreporting.common.shared.RepTimeSeries; -import org.gcube.portlets.user.reportgenerator.client.model.ExportManifestationType; +import org.gcube.portlets.d4sreporting.common.shared.Table; +import org.gcube.portlets.user.exporter.shared.TypeExporter; import org.gcube.portlets.user.reportgenerator.shared.SessionInfo; import com.google.gwt.user.client.rpc.AsyncCallback; @@ -11,7 +11,6 @@ import com.google.gwt.user.client.rpc.AsyncCallback; * * Service interface for server Async communication * @author Massimiliano Assante, ISTI-CNR - massimiliano.assante@isti.cnr.it * - * @version november 2011 (3.0) */ public interface ReportServiceAsync { @@ -74,4 +73,6 @@ public interface ReportServiceAsync { void readImportedModel(String tempPath, AsyncCallback callback); + void save(String filePath, String workspaceFolderId, String ItemName, + TypeExporter type, boolean overwrite, 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 d08ccd0..036d4aa 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 @@ -8,6 +8,7 @@ import org.gcube.portlets.user.reportgenerator.client.targets.DoubleColumnPanel; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Widget; @@ -49,7 +50,6 @@ public class WorkspacePanel extends Composite { public static WorkspacePanel get() { return singleton; } - /** * the panel for the layout of the working space */ diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/ExportOptions.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/ExportOptions.java new file mode 100644 index 0000000..8da0fb0 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/ExportOptions.java @@ -0,0 +1,84 @@ +package org.gcube.portlets.user.reportgenerator.client.uibinder; + +import org.gcube.portlets.user.exporter.shared.TypeExporter; +import org.gcube.portlets.user.reportgenerator.client.ReportServiceAsync; +import org.gcube.portlets.user.reportgenerator.client.ToolboxPanel; +import org.gcube.portlets.user.reportgenerator.client.Presenter.Presenter; + +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.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.Widget; + +public class ExportOptions extends Composite { + + private static ExportOptionsUiBinder uiBinder = GWT + .create(ExportOptionsUiBinder.class); + + interface ExportOptionsUiBinder extends UiBinder { + } + enum ExportMode {SAVE_OPEN, SAVE, SAVE_AS } + + ToolboxPanel tbp; + @UiField HTML saveOpen; + @UiField HTML save; + @UiField HTML saveAs; + + + private String filePath; + private String itemName; + private String workspaceFolderId; + private TypeExporter type; + private ReportServiceAsync rpc; + private Presenter p; + + public ExportOptions(Presenter p, ToolboxPanel tbp, final String filePath, final String itemName, final TypeExporter type, ReportServiceAsync rpc) { + initWidget(uiBinder.createAndBindUi(this)); + this.tbp = tbp; + this.filePath = filePath; + this.itemName = itemName; + this.type= type; + this.rpc = rpc; + this.p = p; + workspaceFolderId = null; + } + + @UiHandler("saveOpen") + void onSaveOpenClick(ClickEvent e) { + GWT.log("SaveOPen"); + doCallBack(ExportMode.SAVE_OPEN); + } + + @UiHandler("save") + void onSaveClick(ClickEvent e) { + doCallBack(ExportMode.SAVE); + } + + @UiHandler("saveAs") + void onSaveAs(ClickEvent e) { + doCallBack(ExportMode.SAVE_AS); + } + + + private void doCallBack(ExportMode mode) { + rpc.save(filePath, workspaceFolderId, itemName, type, true, new AsyncCallback() { + @Override + public void onSuccess(String createdItemId) { + p.clearExportPanel(); + tbp.showExportedVersion(createdItemId, itemName); + Window.alert("Success "); + } + + @Override + public void onFailure(Throwable caught) { + Window.alert("Error: " + caught.getMessage()); + } + }); + } +} diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/ExportOptions.ui.xml b/src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/ExportOptions.ui.xml new file mode 100644 index 0000000..7af02a9 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/uibinder/ExportOptions.ui.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + +
+
+ Exporting Completed Succesfully
+
+ Save & Open + + Save + + Save As +
+
+
\ 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 fd3c2b1..26ec672 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 @@ -47,6 +47,9 @@ import org.gcube.portlets.d4sreporting.common.shared.RepTimeSeries; import org.gcube.portlets.d4sreporting.common.shared.RepeatableSequence; import org.gcube.portlets.d4sreporting.common.shared.Table; import org.gcube.portlets.d4sreporting.common.shared.TableCell; +import org.gcube.portlets.user.exporter.shared.SaveReportFileException; +import org.gcube.portlets.user.exporter.shared.SaveReportFileExistException; +import org.gcube.portlets.user.exporter.shared.TypeExporter; import org.gcube.portlets.user.homelibrary.home.HomeLibrary; import org.gcube.portlets.user.homelibrary.home.exceptions.HomeNotFoundException; import org.gcube.portlets.user.homelibrary.home.exceptions.InternalErrorException; @@ -1651,6 +1654,47 @@ public class ReportServiceImpl extends RemoteServiceServlet implements ReportSe } + @Override + public String save(String filePath, String workspaceFolderId, String itemName, TypeExporter type, boolean overwrite) throws SaveReportFileException, SaveReportFileExistException { + try { + File file = new File(filePath); + + Workspace workspace = HomeLibrary.getUserWorkspace(getASLSession()); + _log.info("Saving in Workspace of " + workspace.getOwner().getPortalLogin()); + WorkspaceFolder folder = (workspaceFolderId != null)? + (WorkspaceFolder)workspace.getItem(workspaceFolderId):workspace.getRoot(); + + if (workspace.exists(itemName, folder.getId())) { + if (overwrite) + workspace.remove(itemName, folder.getId()); + else + throw new SaveReportFileException("The item " + itemName + " already exists"); + } + + switch (type) { + case PDF: + return folder.createExternalPDFFileItem(itemName + "." + type.toString().toLowerCase(), + "", null, new FileInputStream(file)).getId(); + + case HTML: + return folder.createExternalFileItem(itemName + "." + type.toString().toLowerCase(), + "", "text/html", new FileInputStream(file)).getId(); + case DOCX: + return folder.createExternalFileItem(itemName + "." + type.toString().toLowerCase(), + "", "application/msword", new FileInputStream(file)).getId(); + + case XML: + return folder.createExternalFileItem(itemName + "." + type.toString().toLowerCase(), + "", "application/xml", new FileInputStream(file)).getId(); + } + throw new SaveReportFileException("Unknown file type"); + } catch (ItemAlreadyExistException e) { + throw new SaveReportFileExistException(e.getMessage()); + } catch (Exception e) { + throw new SaveReportFileException(e.getMessage()); + } + } + diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/shared/ReportExporterException.java b/src/main/java/org/gcube/portlets/user/reportgenerator/shared/ReportExporterException.java new file mode 100644 index 0000000..602a2a5 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/shared/ReportExporterException.java @@ -0,0 +1,25 @@ +package org.gcube.portlets.user.reportgenerator.shared; + +import java.io.Serializable; + +public class ReportExporterException extends Exception implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -1020757346366625622L; + private String error; + + public ReportExporterException() { + + } + + public ReportExporterException(String error) { + this.error = error; + } + + @Override + public String getMessage() { + return error; + } +} diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/shared/SaveReportFileException.java b/src/main/java/org/gcube/portlets/user/reportgenerator/shared/SaveReportFileException.java new file mode 100644 index 0000000..2b13610 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/shared/SaveReportFileException.java @@ -0,0 +1,16 @@ +package org.gcube.portlets.user.reportgenerator.shared; + + + +public class SaveReportFileException extends ReportExporterException { + + private static final long serialVersionUID = -6674611825830219782L; + + public SaveReportFileException() { + + } + + public SaveReportFileException(String error) { + super(error); + } +} diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/shared/SaveReportFileExistException.java b/src/main/java/org/gcube/portlets/user/reportgenerator/shared/SaveReportFileExistException.java new file mode 100644 index 0000000..a88e523 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/shared/SaveReportFileExistException.java @@ -0,0 +1,18 @@ +package org.gcube.portlets.user.reportgenerator.shared; + +public class SaveReportFileExistException extends ReportExporterException { + + /** + * + */ + private static final long serialVersionUID = 7241356056474394295L; + + public SaveReportFileExistException() { + + } + + public SaveReportFileExistException(String error) { + super(error); + } + +} diff --git a/src/main/webapp/ReportGenerator.css b/src/main/webapp/ReportGenerator.css index d2c2536..c5506f3 100644 --- a/src/main/webapp/ReportGenerator.css +++ b/src/main/webapp/ReportGenerator.css @@ -1,5 +1,51 @@ @import url('reports/old-dialog.css'); +.exportPanel { + margin: 10px 5px 5px 20px; + border: 1px solid #e3e8f3; + padding: 10px; + background-color: #FFFFBF; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + width: 775px; +} +.exportResult { + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 18px; + color: #444; + margin-bottom: 20px; +} +.exportOption { + display: block; + height: 148px; + width: 250px; + opacity: 0.8; + text-align: center; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 18px; + color: #444; +} + +.exportOption:hover { + cursor: pointer; + cursor: hand; + opacity: 1.0; +} + +.optionSave { + background: url('images/save.png') 55% 25px no-repeat; +} + +.optionSaveAs { + background: url('images/save_as.png') 60% 25px no-repeat; +} + +.optionSaveOpen { + background: url('images/save_open.png') 55% 25px no-repeat; +} + + .closeImage { background: url(images/close.png) 0px 0px no-repeat; height: 15px; diff --git a/src/main/webapp/images/save.png b/src/main/webapp/images/save.png new file mode 100644 index 0000000000000000000000000000000000000000..fbb8d7e4ca61a100ed8b6b16f11bd4e15be0bb05 GIT binary patch literal 5768 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 literal 0 HcmV?d00001 diff --git a/src/main/webapp/images/save_open.png b/src/main/webapp/images/save_open.png new file mode 100644 index 0000000000000000000000000000000000000000..995717f4cc4840f1b439bee18d243857c148345d GIT binary patch literal 7780 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 Yyx?7Ixh6gPd+)2Irln+a literal 0 HcmV?d00001