diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentCockpitEditorBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentCockpitEditorBean.java index 905cc5bc2dba13da609b23ef20777753757f0540..64848bafef88be3f79c3a5269b8d5fddd16de466 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentCockpitEditorBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentCockpitEditorBean.java @@ -85,6 +85,7 @@ public final class CurrentCockpitEditorBean { private long timeStamp; private String projectName; private MIProject project; + private boolean unsavedModifications; private MIView activeView; private Dashboard dashboard; private DashboardModel dashboardModel; @@ -136,6 +137,10 @@ public final class CurrentCockpitEditorBean { this.dashboard.setModel(this.dashboardModel); } + public synchronized boolean isUnsavedModification() { + return this.unsavedModifications; + } + /** * Fills the initial dashboard object. */ @@ -201,6 +206,8 @@ public final class CurrentCockpitEditorBean { // Update the class loader and the specific classes used within various methods in this bean this.fillDashboard(); } + + this.unsavedModifications = false; } } catch (final ProjectLoadException ex) { CurrentCockpitEditorBean.LOG.error("An error occured while loading the project.", ex); @@ -304,6 +311,8 @@ public final class CurrentCockpitEditorBean { GlobalPropertiesBean.showMessage(FacesMessage.SEVERITY_INFO, this.globalPropertiesBean.getMsgProjectSaved()); // Update the time stamp! this.resetTimeStamp(); + + this.clearModificationsFlag(); } catch (final IOException ex) { CurrentCockpitEditorBean.LOG.error("An error occured while saving the projet.", ex); GlobalPropertiesBean.showMessage(FacesMessage.SEVERITY_ERROR, "An error occured while saving the project."); @@ -318,6 +327,24 @@ public final class CurrentCockpitEditorBean { } } + /** + * This method sets the property {@link CurrentCockpitEditorBean#unsavedModifications} to false and refreshes the necessary components within the editor to make + * this visible. + */ + private synchronized void clearModificationsFlag() { + this.unsavedModifications = false; + RequestContext.getCurrentInstance().update("menuForm"); + } + + /** + * This method sets the property {@link CurrentCockpitEditorBean#unsavedModifications} to true and refreshes the necessary components within the editor + * to make this visible. + */ + private synchronized void setModificationsFlag() { + this.unsavedModifications = true; + RequestContext.getCurrentInstance().update("menuForm"); + } + /** * This method sets the time stamp to the current system time. */ @@ -338,6 +365,8 @@ public final class CurrentCockpitEditorBean { view.setName(viewName); view.setDescription("No description available."); this.project.getViews().add(view); + + this.setModificationsFlag(); } } @@ -366,6 +395,8 @@ public final class CurrentCockpitEditorBean { */ public synchronized void deleteView(final MIView view) { this.project.getViews().remove(view); + + this.setModificationsFlag(); } /** @@ -399,6 +430,8 @@ public final class CurrentCockpitEditorBean { panel.getChildren().add(text); this.currId++; + + this.setModificationsFlag(); } } diff --git a/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml b/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml index 54ba81e27ce926eb0bcd24ed8de51d6b113105c6..05991f6c3f8f7d113b7988212c6d36dcdbf90a78 100644 --- a/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml +++ b/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml @@ -104,7 +104,8 @@ </c:if> <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-settings" value=" #{localizedMessages.settings}" onclick="settingsDlg.show()" ajax="true"/> <p:separator /> - <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-close" value=" #{localizedMessages.closeProject}" action="ProjectOverviewPage.xhtml?faces-redirect=true" ajax="false"/> + <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-close" value=" #{localizedMessages.closeProject}" onclick="closeConfirmation.show()" ajax="true" rendered="#{currentAnalysisEditorBean.unsavedModification}"/> + <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-close" value=" #{localizedMessages.closeProject}" action="ProjectOverviewPage.xhtml?faces-redirect=true" ajax="false" rendered="#{not currentAnalysisEditorBean.unsavedModification}"/> </p:submenu> <p:submenu label="Graph"> @@ -303,6 +304,13 @@ </ui:define> <ui:define name="furtherDialogIncludes"> + <p:confirmDialog id="confirmDialog" message="You have unsaved changed on your page. Do you really want to continue?" header="Unsaved Changes" severity="alert" widgetVar="closeConfirmation" > + <h:form> + <p:commandButton id="confirm" value="#{localizedMessages.yes}" ajax="false" oncomplete="closeConfirmation.hide()" action="ProjectOverviewPage.xhtml?faces-redirect=true" /> + <p:commandButton id="decline" value="#{localizedMessages.cancel}" onclick="closeConfirmation.hide()" type="button" /> + </h:form> + </p:confirmDialog> + <c:if test="#{sec:areAnyGranted('User, Administrator')}"> <ui:include src="../dialogs/AnalysisEditorPageDialogs.xhtml" /> </c:if> diff --git a/Kieker.WebGUI/src/main/webapp/pages/CockpitEditorPage.xhtml b/Kieker.WebGUI/src/main/webapp/pages/CockpitEditorPage.xhtml index 1bcca305cd1b6847f1fe6cf752ed8966961cb93f..d8bb83b75f32b531482e7ee161eac42b17574742 100644 --- a/Kieker.WebGUI/src/main/webapp/pages/CockpitEditorPage.xhtml +++ b/Kieker.WebGUI/src/main/webapp/pages/CockpitEditorPage.xhtml @@ -11,7 +11,7 @@ <h:body> <ui:composition template="/templates/PagesTemplate.xhtml"> - <ui:param name="unsavedModifications" value="false"/> + <ui:param name="unsavedModifications" value="#{currentCockpitEditorBean.unsavedModification}"/> <ui:param name="projectName" value="#{currentCockpitEditorBean.projectName}"/> <ui:param name="pagename" value="cockpitEditor"/> <ui:param name="showProjectName" value="true"/> @@ -58,7 +58,8 @@ <p:separator/> <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-settings" value=" #{localizedMessages.settings}" onclick="settingsDlg.show()" ajax="true"/> <p:separator /> - <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-close" value=" #{localizedMessages.closeProject}" action="ProjectOverviewPage.xhtml?faces-redirect=true" ajax="false"/> + <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-close" value=" #{localizedMessages.closeProject}" onclick="closeConfirmation.show()" ajax="true" rendered="#{currentCockpitEditorBean.unsavedModification}"/> + <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-close" value=" #{localizedMessages.closeProject}" action="ProjectOverviewPage.xhtml?faces-redirect=true" ajax="false" rendered="#{not currentCockpitEditorBean.unsavedModification}"/> </p:submenu> </ui:define> @@ -142,6 +143,13 @@ </ui:define> <ui:define name="furtherDialogIncludes"> + <p:confirmDialog id="confirmDialog" message="You have unsaved changed on your page. Do you really want to continue?" header="Unsaved Changes" severity="alert" widgetVar="closeConfirmation" > + <h:form> + <p:commandButton id="confirm" value="#{localizedMessages.yes}" ajax="false" oncomplete="closeConfirmation.hide()" action="ProjectOverviewPage.xhtml?faces-redirect=true" /> + <p:commandButton id="decline" value="#{localizedMessages.cancel}" onclick="closeConfirmation.hide()" type="button" /> + </h:form> + </p:confirmDialog> + <!-- Include the dialogs for the views. --> <ui:include src="../dialogs/CockpitEditorPageDialogs.xhtml" /> </ui:define> diff --git a/Kieker.WebGUI/src/main/webapp/templates/PagesTemplate.xhtml b/Kieker.WebGUI/src/main/webapp/templates/PagesTemplate.xhtml index 70d76affcb64c24d47e8192eb5ac72531b52cfe0..25824ef44b5843b6d87a191420190a6cd5b666fc 100644 --- a/Kieker.WebGUI/src/main/webapp/templates/PagesTemplate.xhtml +++ b/Kieker.WebGUI/src/main/webapp/templates/PagesTemplate.xhtml @@ -25,28 +25,45 @@ <h:outputText styleClass="kieker-title" value="Kieker #{showProjectName ? '»' : ''} #{showProjectName ? stringBean.shortenLongName(projectName, 30) : ''}#{unsavedModifications ? '*' : ''}"/> </p:toolbarGroup> <p:toolbarGroup align="right"> - <p:button styleClass="perspective-button" icon="ui-icon-home" outcome="projectOverview" disabled="#{pagename == 'projectOverview'}" /> + + <p:commandButton styleClass="perspective-button" icon="ui-icon-home" onclick="toHomeConfirmation.show()" disabled="#{pagename == 'projectOverview'}" rendered="#{unsavedModifications}" /> + <p:button styleClass="perspective-button" icon="ui-icon-home" outcome="projectOverview" disabled="#{pagename == 'projectOverview'}" rendered="#{not unsavedModifications}" /> + <p:separator/> - <p:button styleClass="perspective-button" icon="ui-icon-analysisEditor" value="#{localizedMessages.analysisEditor}" outcome="analysisEditor" disabled="#{pagename == 'analysisEditor' or empty projectName}"> + + <p:commandButton styleClass="perspective-button" icon="ui-icon-analysisEditor" value="#{localizedMessages.analysisEditor}" onclick="toAnalysisEditorConfirmation.show()" disabled="#{pagename == 'analysisEditor' or empty projectName}" rendered="#{unsavedModifications}" /> + <p:button styleClass="perspective-button" icon="ui-icon-analysisEditor" value="#{localizedMessages.analysisEditor}" outcome="analysisEditor" disabled="#{pagename == 'analysisEditor' or empty projectName}" rendered="#{not unsavedModifications}" > <f:param name="projectName" value="#{projectName}" rendered="#{not empty projectName}"/> </p:button> + <c:if test="#{sec:areAnyGranted('User, Administrator')}"> - <p:button styleClass="perspective-button" icon="ui-icon-analysis" value="#{localizedMessages.analysis}" outcome="controller" disabled="#{pagename == 'controller' or empty projectName}"> + <p:commandButton styleClass="perspective-button" icon="ui-icon-analysis" value="#{localizedMessages.analysis}" onclick="toControllerConfirmation.show()" disabled="#{pagename == 'controller' or empty projectName}" rendered="#{unsavedModifications}" /> + <p:button styleClass="perspective-button" icon="ui-icon-analysis" value="#{localizedMessages.analysis}" outcome="controller" disabled="#{pagename == 'controller' or empty projectName}" rendered="#{not unsavedModifications}" > <f:param name="projectName" value="#{projectName}" rendered="#{not empty projectName}"/> </p:button> </c:if> + <p:separator/> + <c:if test="#{sec:areAnyGranted('User, Administrator')}"> - <p:button styleClass="perspective-button" icon="ui-icon-cockpitEditor" value="#{localizedMessages.cockpitEditor}" outcome="cockpitEditor" disabled="#{pagename == 'cockpitEditor' or empty projectName}"> + <p:commandButton styleClass="perspective-button" icon="ui-icon-cockpitEditor" value="#{localizedMessages.cockpitEditor}" onclick="toCockpitEditorConfirmation.show()" disabled="#{pagename == 'cockpitEditor' or empty projectName}" rendered="#{unsavedModifications}" /> + <p:button styleClass="perspective-button" icon="ui-icon-cockpitEditor" value="#{localizedMessages.cockpitEditor}" outcome="cockpitEditor" disabled="#{pagename == 'cockpitEditor' or empty projectName}" rendered="#{not unsavedModifications}" > <f:param name="projectName" value="#{projectName}" rendered="#{not empty projectName}"/> </p:button> </c:if> - <p:button styleClass="perspective-button" icon="ui-icon-cockpit" value="#{localizedMessages.cockpit}" outcome="cockpit" disabled="#{pagename == 'cockpit' or empty projectName}"> + + <p:commandButton styleClass="perspective-button" icon="ui-icon-cockpit" value="#{localizedMessages.cockpit}" onclick="toCockpitConfirmation.show()" disabled="#{pagename == 'cockpit' or empty projectName}" rendered="#{unsavedModifications}" /> + <p:button styleClass="perspective-button" icon="ui-icon-cockpit" value="#{localizedMessages.cockpit}" outcome="cockpit" disabled="#{pagename == 'cockpit' or empty projectName}" rendered="#{not unsavedModifications}" > <f:param name="projectName" value="#{projectName}" rendered="#{not empty projectName}"/> </p:button> + <c:if test="#{sec:areAnyGranted('Administrator')}"> <p:separator/> - <p:button styleClass="perspective-button" icon="ui-icon-userManagement" value="User Management" outcome="userManagement" disabled="#{pagename == 'userManagement'}" /> + + <p:commandButton styleClass="perspective-button" icon="ui-icon-userManagement" value="User Management" onclick="toUserManagmentConfirmation.show()" disabled="#{pagename == 'userManagement'}" rendered="#{unsavedModifications}" /> + <p:button styleClass="perspective-button" icon="ui-icon-userManagement" value="User Management" outcome="userManagement" disabled="#{pagename == 'userManagement'}" rendered="#{not unsavedModifications}" > + <f:param name="projectName" value="#{projectName}" rendered="#{not empty projectName}"/> + </p:button> </c:if> </p:toolbarGroup> </p:toolbar> @@ -61,7 +78,8 @@ <p:menuitem styleClass="element-with-whitespace" icon="ui-icon-about" value=" #{localizedMessages.about}" onclick="aboutDlg.show()" ajax="true"/> </p:submenu> - <p:menuitem styleClass="logOutButton element-with-whitespace" icon="ui-icon-logout" value=" #{userBean.username} (#{userBean.userrole})" ajax="true" url="#{request.contextPath}/j_spring_security_logout"/> + <p:menuitem styleClass="logOutButton element-with-whitespace" icon="ui-icon-logout" value=" #{userBean.username} (#{userBean.userrole})" ajax="true" url="#{request.contextPath}/j_spring_security_logout" rendered="#{not unsavedModifications}"/> + <p:menuitem styleClass="logOutButton element-with-whitespace" icon="ui-icon-logout" value=" #{userBean.username} (#{userBean.userrole})" onclick="logOutConfirmation.show()" ajax="true" rendered="#{unsavedModifications}"/> </p:menubar> <ui:insert name="furtherMenuBar"/> </h:form> @@ -76,6 +94,57 @@ </p:layout> + <p:confirmDialog message="You have unsaved changed on your page. Do you really want to continue?" header="Unsaved Changes" severity="alert" widgetVar="toHomeConfirmation" > + <h:form> + <p:commandButton id="confirm" value="#{localizedMessages.yes}" ajax="false" oncomplete="toHomeConfirmation.hide()" action="ProjectOverviewPage.xhtml?faces-redirect=true" /> + <p:commandButton id="decline" value="#{localizedMessages.cancel}" onclick="toHomeConfirmation.hide()" type="button" /> + </h:form> + </p:confirmDialog> + <p:confirmDialog message="You have unsaved changed on your page. Do you really want to continue?" header="Unsaved Changes" severity="alert" widgetVar="toAnalysisEditorConfirmation" > + <h:form> + <p:button id="confirm" value="#{localizedMessages.yes}" outcome="analysisEditor"> + <f:param name="projectName" value="#{projectName}" rendered="#{not empty projectName}"/> + </p:button> + <p:commandButton id="decline" value="#{localizedMessages.cancel}" onclick="toAnalysisEditorConfirmation.hide()" type="button" /> + </h:form> + </p:confirmDialog> + <p:confirmDialog message="You have unsaved changed on your page. Do you really want to continue?" header="Unsaved Changes" severity="alert" widgetVar="toControllerConfirmation" > + <h:form> + <p:button id="confirm" value="#{localizedMessages.yes}" outcome="controller"> + <f:param name="projectName" value="#{projectName}" rendered="#{not empty projectName}"/> + </p:button> + <p:commandButton id="decline" value="#{localizedMessages.cancel}" onclick="toControllerConfirmation.hide()" type="button" /> + </h:form> + </p:confirmDialog> + <p:confirmDialog message="You have unsaved changed on your page. Do you really want to continue?" header="Unsaved Changes" severity="alert" widgetVar="toCockpitEditorConfirmation" > + <h:form> + <p:button id="confirm" value="#{localizedMessages.yes}" outcome="cockpitEditor"> + <f:param name="projectName" value="#{projectName}" rendered="#{not empty projectName}"/> + </p:button> + <p:commandButton id="decline" value="#{localizedMessages.cancel}" onclick="toCockpitEditorConfirmation.hide()" type="button" /> + </h:form> + </p:confirmDialog> + <p:confirmDialog message="You have unsaved changed on your page. Do you really want to continue?" header="Unsaved Changes" severity="alert" widgetVar="toCockpitConfirmation" > + <h:form> + <p:button id="confirm" value="#{localizedMessages.yes}" outcome="cockpit"> + <f:param name="projectName" value="#{projectName}" rendered="#{not empty projectName}"/> + </p:button> + <p:commandButton id="decline" value="#{localizedMessages.cancel}" onclick="toCockpitConfirmation.hide()" type="button" /> + </h:form> + </p:confirmDialog> + <p:confirmDialog message="You have unsaved changed on your page. Do you really want to continue?" header="Unsaved Changes" severity="alert" widgetVar="toUserManagmentConfirmation" > + <h:form> + <p:button id="confirm" value="#{localizedMessages.yes}" outcome="userManagement"/> + <p:commandButton id="decline" value="#{localizedMessages.cancel}" onclick="toUserManagmentConfirmation.hide()" type="button" /> + </h:form> + </p:confirmDialog> + <p:confirmDialog message="You have unsaved changed on your page. Do you really want to continue?" header="Unsaved Changes" severity="alert" widgetVar="logOutConfirmation" > + <h:form> + <p:button id="confirm" value="#{localizedMessages.yes}" href="#{request.contextPath}/j_spring_security_logout"/> + <p:commandButton id="decline" value="#{localizedMessages.cancel}" onclick="logOutConfirmation.hide()" type="button" /> + </h:form> + </p:confirmDialog> + <!-- Include the about-dialog. --> <ui:include src="../dialogs/AboutDialog.xhtml" /> <!-- Include the dialog for the configuration. -->