From f06efd3fbf78ea8203be495ef0f25504c8199b6f Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Tue, 6 Jun 2017 09:26:23 +0200
Subject: [PATCH] OO-2790: add persistence to the collpased panels in QTI 1.2
 course element for users

---
 .../olat/course/nodes/iq/IQRunController.java | 49 ++++++++++---
 .../course/nodes/iq/_content/testrun.html     | 72 +++++++++++++------
 2 files changed, 89 insertions(+), 32 deletions(-)

diff --git a/src/main/java/org/olat/course/nodes/iq/IQRunController.java b/src/main/java/org/olat/course/nodes/iq/IQRunController.java
index 040f40db83d..6182d38a1c2 100644
--- a/src/main/java/org/olat/course/nodes/iq/IQRunController.java
+++ b/src/main/java/org/olat/course/nodes/iq/IQRunController.java
@@ -61,6 +61,7 @@ import org.olat.core.util.UserSession;
 import org.olat.core.util.Util;
 import org.olat.core.util.event.EventBus;
 import org.olat.core.util.event.GenericEventListener;
+import org.olat.core.util.prefs.Preferences;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.core.util.vfs.VFSContainer;
 import org.olat.course.CourseFactory;
@@ -366,6 +367,7 @@ public class IQRunController extends BasicController implements GenericEventList
 					myContent.put("disc", iFrameCtr.getInitialComponent());
 					iFrameCtr.setCurrentURI(sDisclaimer);
 					myContent.contextPut("hasDisc", Boolean.TRUE);
+					myContent.contextPut("in-disclaimer", isPanelOpen(ureq, "disclaimer", true));
 				}
 			}
 		}
@@ -489,6 +491,10 @@ public class IQRunController extends BasicController implements GenericEventList
 			} 
 		} else if (source == hideResultsButton) {
 			myContent.contextPut("showResults", Boolean.FALSE);
+		} else if("show".equals(event.getCommand())) {
+			saveOpenPanel(ureq, ureq.getParameter("panel"), true);
+		} else if("hide".equals(event.getCommand())) {
+			saveOpenPanel(ureq, ureq.getParameter("panel"), false);
 		}
 	}
 
@@ -641,6 +647,7 @@ public class IQRunController extends BasicController implements GenericEventList
 	    			if(acn.hasCommentConfigured()) {
 	    				StringBuilder comment = Formatter.stripTabsAndReturns(assessmentEntry.getComment());
 	    				myContent.contextPut("comment", StringHelper.xssScan(comment));
+						myContent.contextPut("in-comment", isPanelOpen(ureq, "comment", true));
 	    			}
 
 	    			if(acn.hasIndividualAsssessmentDocuments()) {
@@ -648,6 +655,7 @@ public class IQRunController extends BasicController implements GenericEventList
 						String mapperUri = registerCacheableMapper(ureq, null, new DocumentsMapper(docs));
 						myContent.contextPut("docsMapperUri", mapperUri);
 						myContent.contextPut("docs", docs);
+						myContent.contextPut("in-assessmentDocuments", isPanelOpen(ureq, "assessmentDocuments", true));
 	    			}
 	    		}
 	    		myContent.contextPut("attempts", assessmentEntry.getAttempts() == null ? 0 : assessmentEntry.getAttempts());
@@ -699,24 +707,25 @@ public class IQRunController extends BasicController implements GenericEventList
     //migration: check if old tests have no summary configured
 	  String configuredSummary = (String) modConfig.get(IQEditController.CONFIG_KEY_SUMMARY);
 	  boolean noSummary = configuredSummary==null || (configuredSummary!=null && configuredSummary.equals(AssessmentInstance.QMD_ENTRY_SUMMARY_NONE));
-		if(!noSummary) {
+	  if(!noSummary) {
 			Boolean showResultsObj = modConfig.getBooleanEntry(IQEditController.CONFIG_KEY_RESULT_ON_HOME_PAGE);		
 			boolean showResultsOnHomePage = (showResultsObj!=null && showResultsObj.booleanValue());
-			myContent.contextPut("showResultsOnHomePage",new Boolean(showResultsOnHomePage));			
+			myContent.contextPut("showResultsOnHomePage",new Boolean(showResultsOnHomePage));
+			myContent.contextPut("in-results", isPanelOpen(ureq, "results", true));
 			boolean dateRelatedVisibility = AssessmentHelper.isResultVisible(modConfig);		
 			if(showResultsOnHomePage && dateRelatedVisibility) {
 				myContent.contextPut("showResultsVisible",Boolean.TRUE);
-			  showResultsButton = LinkFactory.createButton("command.showResults", myContent, this);
-			  hideResultsButton = LinkFactory.createButton("command.hideResults", myContent, this);
+				showResultsButton = LinkFactory.createButton("command.showResults", myContent, this);
+				hideResultsButton = LinkFactory.createButton("command.hideResults", myContent, this);
 			} else if(showResultsOnHomePage) {
 				Date startDate = (Date)modConfig.get(IQEditController.CONFIG_KEY_RESULTS_START_DATE);
-			  Date endDate = (Date)modConfig.get(IQEditController.CONFIG_KEY_RESULTS_END_DATE);
-			  String visibilityStartDate = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, ureq.getLocale()).format(startDate);
-			  String visibilityEndDate = "-";
-			  if(endDate!=null) {
-			    visibilityEndDate = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, ureq.getLocale()).format(endDate);
-			  }
-			  String visibilityPeriod = getTranslator().translate("showResults.visibility", new String[] { visibilityStartDate, visibilityEndDate});
+				Date endDate = (Date)modConfig.get(IQEditController.CONFIG_KEY_RESULTS_END_DATE);
+			  	String visibilityStartDate = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, ureq.getLocale()).format(startDate);
+			  	String visibilityEndDate = "-";
+			  	if(endDate!=null) {
+				  	visibilityEndDate = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, ureq.getLocale()).format(endDate);
+			  	}
+			  	String visibilityPeriod = getTranslator().translate("showResults.visibility", new String[] { visibilityStartDate, visibilityEndDate});
 				myContent.contextPut("visibilityPeriod",visibilityPeriod);
 				myContent.contextPut("showResultsVisible",Boolean.FALSE);
 			}
@@ -731,6 +740,24 @@ public class IQRunController extends BasicController implements GenericEventList
 		myContent.contextPut("attempts", am.getNodeAttempts(courseNode, identity));
 	}
 	
+	private boolean isPanelOpen(UserRequest ureq, String panelId, boolean def) {
+		Preferences guiPrefs = ureq.getUserSession().getGuiPreferences();
+		Boolean showConfig  = (Boolean) guiPrefs.get(IQRunController.class, getOpenPanelId(panelId));
+		return showConfig == null ? def : showConfig.booleanValue();
+	}
+	
+	private void saveOpenPanel(UserRequest ureq, String panelId, boolean newValue) {
+		Preferences guiPrefs = ureq.getUserSession().getGuiPreferences();
+		if (guiPrefs != null) {
+			guiPrefs.putAndSave(IQRunController.class, getOpenPanelId(panelId), new Boolean(newValue));
+		}
+		myContent.contextPut("in-" + panelId, new Boolean(newValue));
+	}
+	
+	private String getOpenPanelId(String panelId) {
+		return panelId + "::" + userCourseEnv.getCourseEnvironment().getCourseResourceableId() + "::" + courseNode.getIdent();
+	}
+	
 	/**
 	 * 
 	 * @see org.olat.core.gui.control.DefaultController#doDisspose(boolean)
diff --git a/src/main/java/org/olat/course/nodes/iq/_content/testrun.html b/src/main/java/org/olat/course/nodes/iq/_content/testrun.html
index 1db132f001c..f5e85abc3c9 100644
--- a/src/main/java/org/olat/course/nodes/iq/_content/testrun.html
+++ b/src/main/java/org/olat/course/nodes/iq/_content/testrun.html
@@ -60,25 +60,27 @@
 			</table>
 		</div>
 	
-		#if ($comment)		
+		#if ($r.isNotEmpty($comment))		
 		<div class="panel panel-default o_comment">
 		  	<div class="panel-heading" data-toggle="collapse" data-target="#collapseComment">
 	  			<h4 class="panel-title">
-	  				<i id="collapseCommentsToggler" class="o_icon o_icon-fw o_icon_close_togglebox"> </i>
+	  				<i id="collapseCommentsToggler" class="o_icon o_icon-fw #if($r.isTrue($in-comment)) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i>
 	  				$r.translate("comment.yourcomment")
 	  			</h4>
 	  		</div>
-		<div id="collapseComment" class="panel-collapse collapse in"><div class="panel-body">
+			<div id="collapseComment" class="panel-collapse collapse #if($r.isTrue($in-comment)) in #end"><div class="panel-body">
 				$comment
-	  		</div>
-		</div></div>
+	  		</div></div>
+	  	</div>
 		<script type="text/javascript">
 			/* <![CDATA[ */
 				jQuery('#collapseComment').on('hide.bs.collapse', function () {
-						jQuery('#collapseCommentsToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox');
+					jQuery('#collapseCommentsToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox');
+					$r.backgroundCommand("hide","panel","comment")
 				})
 				jQuery('#collapseComment').on('show.bs.collapse', function () {
-						jQuery('#collapseCommentsToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox');
+					jQuery('#collapseCommentsToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox');
+					$r.backgroundCommand("show","panel","comment")
 				})
 			/* ]]> */
 		</script>
@@ -88,11 +90,11 @@
 		<div class="panel panel-default o_assessment_docs">
 		  	<div class="panel-heading" data-toggle="collapse" data-target="#collapseAssessmentDocuments">
 		  		<h4 class="panel-title">
-		  			<i id="collapseAssessmentDocumentsToggler" class="o_icon o_icon-fw o_icon_close_togglebox"> </i>
+		  			<i id="collapseAssessmentDocumentsToggler" class="o_icon o_icon-fw #if($r.isTrue($in-assessmentDocuments)) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i>
 		  			$r.translate("assessment.documents.title")
 		  		</h4>
 		  	</div>
-			<div id="collapseAssessmentDocuments" class="panel-collapse collapse in"><div class="panel-body">
+			<div id="collapseAssessmentDocuments" class="panel-collapse collapse #if($r.isTrue($in-assessmentDocuments)) in #end"><div class="panel-body">
 				<ul class="list-unstyled">
 				#foreach($doc in $docs)
 					<li><a href="$docsMapperUri/$doc.name" target="_blank"><i class="o_icon o_icon-fw $r.getFiletypeIconCss($doc.name)"> </i> $r.escapeHtml($doc.name) ($r.formatBytes(${doc.length()}))</a></li>
@@ -102,11 +104,13 @@
 		</div>
 		<script type="text/javascript">
 			/* <![CDATA[ */
-				jQuery('#collapseComment').on('hide.bs.collapse', function () {
-						jQuery('#collapseCommentToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox');
+				jQuery('#collapseAssessmentDocuments').on('hide.bs.collapse', function () {
+					jQuery('#collapseAssessmentDocumentsToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox');
+					$r.backgroundCommand("hide","panel","assessmentDocuments")
 				})
-				jQuery('#collapseComment').on('show.bs.collapse', function () {
-						jQuery('#collapseCommentToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox');
+				jQuery('#collapseAssessmentDocuments').on('show.bs.collapse', function () {
+					jQuery('#collapseAssessmentDocumentsToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox');
+					$r.backgroundCommand("show","panel","assessmentDocuments")
 				})
 			/* ]]> */
 		</script>
@@ -133,11 +137,11 @@
 	<div class="panel panel-default o_results">
 	  	<div class="panel-heading" data-toggle="collapse" data-target="#collapseResults">
 	  		<h4 class="panel-title">
-	  			<i id="collapseResultsToggler" class="o_icon o_icon-fw o_icon_close_togglebox"> </i>	  	
+	  			<i id="collapseResultsToggler" class="o_icon o_icon-fw #if($r.isTrue($in-results)) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i>	  	
 		  		$r.translate("showResults.title")
 		  	</h4>
 	  	</div>
-		<div id="collapseResults" class="panel-collapse collapse in"><div class="panel-body">
+		<div id="collapseResults" class="panel-collapse collapse #if($r.isTrue($in-results)) in #end"><div class="panel-body">
 		  	#if($showResultsVisible)
 				#if ($showResults)
 					$r.render("command.hideResults")					  				  
@@ -161,10 +165,12 @@
 	<script type="text/javascript">
 		/* <![CDATA[ */
 			jQuery('#collapseResults').on('hide.bs.collapse', function () {
-					jQuery('#collapseResultsToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox');
+				jQuery('#collapseResultsToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox');
+				$r.backgroundCommand("hide","panel","results")
 			})
 			jQuery('#collapseResults').on('show.bs.collapse', function () {
-					jQuery('#collapseResultsToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox');
+				jQuery('#collapseResultsToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox');
+				$r.backgroundCommand("show","panel","results")
 			})
 		/* ]]> */
 	</script>
@@ -179,13 +185,25 @@
 	<div class="panel panel-default o_disclaimer">
 	  	<div class="panel-heading" data-toggle="collapse" data-target="#collapseDisclaimer">
 	  		<h4 class="panel-title">
-	  			<i id="collapseDisclaimerToggler" class="o_icon o_icon-fw o_icon_close_togglebox"> </i>
+	  			<i id="collapseDisclaimerToggler" class="o_icon o_icon-fw #if($r.isTrue($in-disclaimer)) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i>
 	  			$r.translate("disclaimer")
 	  		</h4>
 	  	</div>
-	  	<div id="collapseDisclaimer" class="panel-collapse collapse in"><div class="panel-body">
+	  	<div id="collapseDisclaimer" class="panel-collapse collapse #if($r.isTrue($in-disclaimer)) in #end"><div class="panel-body">
 		$r.render("disc")
   		</div></div>
+  		<script type="text/javascript">
+		/* <![CDATA[ */
+			jQuery('#collapseDisclaimer').on('hide.bs.collapse', function () {
+				jQuery('#collapseDisclaimerToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox');
+				$r.backgroundCommand("hide","panel","disclaimer")
+			})
+			jQuery('#collapseDisclaimer').on('show.bs.collapse', function () {
+				jQuery('#collapseDisclaimerToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox');
+				$r.backgroundCommand("show","panel","disclaimer")
+			})
+		/* ]]> */
+		</script>
 	</div>
 	#end
 #else
@@ -193,13 +211,25 @@
 	<div class="panel panel-default o_disclaimer">
 	  	<div class="panel-heading" data-toggle="collapse" data-target="#collapseDisclaimer">
 	  		<h4 class="panel-title">
-	  			<i id="collapseDisclaimerToggler" class="o_icon o_icon-fw o_icon_close_togglebox"> </i>
+	  			<i id="collapseDisclaimerToggler" class="o_icon o_icon-fw #if($r.isTrue($in-disclaimer)) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i>
 	  			$r.translate("disclaimer")
 	  		</h4>
 	  	</div>
-	  	<div id="collapseDisclaimer" class="panel-collapse collapse in"><div class="panel-body">
+	  	<div id="collapseDisclaimer" class="panel-collapse collapse #if($r.isTrue($in-disclaimer)) in #end"><div class="panel-body">
 		$r.render("disc")
   		</div></div>
+ 		<script type="text/javascript">
+		/* <![CDATA[ */
+			jQuery('#collapseDisclaimer').on('hide.bs.collapse', function () {
+				jQuery('#collapseDisclaimerToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox');
+				$r.backgroundCommand("hide","panel","disclaimer")
+			})
+			jQuery('#collapseDisclaimer').on('show.bs.collapse', function () {
+				jQuery('#collapseDisclaimerToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox');
+				$r.backgroundCommand("show","panel","disclaimer")
+			})
+		/* ]]> */
+		</script>
 	</div>
 	#end
 	#if ($infobox)		
-- 
GitLab