From 803e7bb50dfce0ea14cc893a8ef915d98d737340 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Tue, 6 Sep 2016 12:02:07 +0200
Subject: [PATCH] OO-1593: add rich text editing for summary and description in
 assignment, page, section and binder...

---
 .../services/mark/impl/ui/MarkController.java |  2 +-
 .../gui/components/dropdown/DropdownItem.java |  2 +-
 .../nodes/members/MembersMailController.java  |  2 +-
 .../nodes/portfolio/PortfolioConfigForm.java  |  6 +--
 .../PortfolioCourseNodeRunController.java     |  4 +-
 .../qti/editor/FeedbackFormController.java    | 12 ++---
 .../portfolio/BinderSecurityCallback.java     |  2 +
 .../BinderSecurityCallbackFactory.java        | 26 ++++++++++
 .../ui/AssignmentEditController.java          |  7 ++-
 .../ui/BinderMetadataEditController.java      |  7 ++-
 .../ui/BinderPageListController.java          |  4 +-
 .../portfolio/ui/BinderPickerController.java  |  2 +-
 .../portfolio/ui/MediaUploadController.java   |  6 ++-
 .../ui/PageMetadataEditController.java        |  9 ++--
 .../portfolio/ui/PageRunController.java       | 37 ++++++++-----
 .../portfolio/ui/SectionEditController.java   |  7 ++-
 .../ui/TableOfContentController.java          | 29 ++++++-----
 .../ui/_i18n/LocalStrings_de.properties       |  3 +-
 .../component/CitationComponentRenderer.java  |  4 +-
 .../component/TimelineComponentRenderer.java  |  3 +-
 .../media/CollectCitationMediaController.java |  6 ++-
 .../ui/media/CollectFileMediaController.java  |  6 ++-
 .../ui/media/CollectImageMediaController.java |  6 ++-
 .../ui/media/CollectTextMediaController.java  |  6 ++-
 .../ui/media/CollectVideoMediaController.java |  6 ++-
 .../ui/media/_content/media_citation.html     |  2 +-
 .../ui/model/PortfolioElementRow.java         |  2 +-
 .../olat/search/ui/SearchInputController.java |  2 +-
 .../org/olat/selenium/PortfolioV2Test.java    |  2 +-
 .../selenium/page/graphene/OOGraphene.java    | 11 ++++
 .../graphene/TinyMCELoadedByIdPredicate.java  | 52 +++++++++++++++++++
 .../selenium/page/portfolio/BinderPage.java   |  7 ++-
 .../selenium/page/portfolio/BindersPage.java  |  4 +-
 33 files changed, 207 insertions(+), 79 deletions(-)
 create mode 100644 src/test/java/org/olat/selenium/page/graphene/TinyMCELoadedByIdPredicate.java

diff --git a/src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkController.java b/src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkController.java
index 1086b58af9a..6be1096c3da 100644
--- a/src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkController.java
+++ b/src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkController.java
@@ -121,7 +121,7 @@ public class MarkController extends FormBasicController {
 			}
 		}
 		
-		((Link)markLink.getComponent()).setTooltip(tooltip);
+		markLink.getComponent().setTooltip(tooltip);
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/core/gui/components/dropdown/DropdownItem.java b/src/main/java/org/olat/core/gui/components/dropdown/DropdownItem.java
index fffcdc76b58..dc52dc7ea88 100644
--- a/src/main/java/org/olat/core/gui/components/dropdown/DropdownItem.java
+++ b/src/main/java/org/olat/core/gui/components/dropdown/DropdownItem.java
@@ -59,7 +59,7 @@ public class DropdownItem extends FormItemImpl implements FormItemCollection {
 	public void addElement(FormLink link) {
 		items.add(link);
 		
-		Link linkCmp = (Link)link.getComponent();
+		Link linkCmp = link.getComponent();
 		linkCmp.setDomReplacementWrapperRequired(false);
 		dropdown.addComponent(linkCmp);
 	}
diff --git a/src/main/java/org/olat/course/nodes/members/MembersMailController.java b/src/main/java/org/olat/course/nodes/members/MembersMailController.java
index 7c6f45413ab..3489e68cfe0 100644
--- a/src/main/java/org/olat/course/nodes/members/MembersMailController.java
+++ b/src/main/java/org/olat/course/nodes/members/MembersMailController.java
@@ -175,7 +175,7 @@ public class MembersMailController extends FormBasicController {
 			addMemberButton = uifactory.addFormLink("add.member", "add", "", "", individualMemberCont, Link.NONTRANSLATED);
 			addMemberButton.setIconLeftCSS("o_icon o_icon-lg o_icon_table_large");
 			addMemberButton.setDomReplacementWrapperRequired(false);
-			((Link)addMemberButton.getComponent()).setSuppressDirtyFormWarning(true);
+			addMemberButton.getComponent().setSuppressDirtyFormWarning(true);
 		}
 
 		String[] extValues = new String[] { translate("contact.external") };
diff --git a/src/main/java/org/olat/course/nodes/portfolio/PortfolioConfigForm.java b/src/main/java/org/olat/course/nodes/portfolio/PortfolioConfigForm.java
index 7d8f441f2f9..3456ff5b91c 100644
--- a/src/main/java/org/olat/course/nodes/portfolio/PortfolioConfigForm.java
+++ b/src/main/java/org/olat/course/nodes/portfolio/PortfolioConfigForm.java
@@ -142,7 +142,7 @@ public class PortfolioConfigForm extends FormBasicController {
 		previewMapLink = uifactory.addFormLink("preview", "selected.map", "selected.map", formLayout, Link.LINK);
 		previewMapLink.setCustomEnabledLinkCSS("o_preview");
 		previewMapLink.setIconLeftCSS("o_icon o_icon-fw o_icon_preview");
-		((Link)previewMapLink.getComponent()).setCustomDisplayText(name);
+		previewMapLink.getComponent().setCustomDisplayText(name);
 		previewMapLink.setVisible(map != null);
 		previewMapLink.setElementCssClass("o_sel_preview_map");
 		
@@ -288,8 +288,8 @@ public class PortfolioConfigForm extends FormBasicController {
 		mapNameElement.setVisible(map == null && binder == null);
 		
 		previewMapLink.setVisible(map != null || binder != null);
-		((Link)previewMapLink.getComponent()).setCustomDisplayText(name);
-		((Link)previewMapLink.getComponent()).setDirty(true);
+		previewMapLink.getComponent().setCustomDisplayText(name);
+		previewMapLink.getComponent().setDirty(true);
 		
 		chooseMapLink.setVisible(map == null && binder == null);
 		changeMapLink.setVisible(map != null || binder != null);
diff --git a/src/main/java/org/olat/course/nodes/portfolio/PortfolioCourseNodeRunController.java b/src/main/java/org/olat/course/nodes/portfolio/PortfolioCourseNodeRunController.java
index 487e325806b..1e910122888 100644
--- a/src/main/java/org/olat/course/nodes/portfolio/PortfolioCourseNodeRunController.java
+++ b/src/main/java/org/olat/course/nodes/portfolio/PortfolioCourseNodeRunController.java
@@ -242,7 +242,7 @@ public class PortfolioCourseNodeRunController extends FormBasicController {
 
 	private void updateSelectedBinderUI() {
 		String copyTitle = StringHelper.escapeHtml(copyBinder.getTitle());
-		((Link)selectMapLink.getComponent()).setCustomDisplayText(copyTitle);
+		selectMapLink.getComponent().setCustomDisplayText(copyTitle);
 		
 		updateCopyDate(copyBinder.getCopyDate());
 		updateAssessmentInfos(copyBinder.getReturnDate());
@@ -251,7 +251,7 @@ public class PortfolioCourseNodeRunController extends FormBasicController {
 
 	private void updateSelectedMapUI() {	
 		String copyTitle = StringHelper.escapeHtml(copyMap.getTitle());
-		((Link)selectMapLink.getComponent()).setCustomDisplayText(copyTitle);
+		selectMapLink.getComponent().setCustomDisplayText(copyTitle);
 		
 		// show results, when already handed in
 		EPStructuredMap structuredMap = (EPStructuredMap)copyMap;
diff --git a/src/main/java/org/olat/ims/qti/editor/FeedbackFormController.java b/src/main/java/org/olat/ims/qti/editor/FeedbackFormController.java
index 48dbd03d6c6..53d134376c2 100644
--- a/src/main/java/org/olat/ims/qti/editor/FeedbackFormController.java
+++ b/src/main/java/org/olat/ims/qti/editor/FeedbackFormController.java
@@ -225,8 +225,8 @@ public class FeedbackFormController extends FormBasicController {
 		RichTextElement masteryFeedback = uifactory.addRichTextElementForStringData("richTextElement", "item_feedback_mastery", masteryMat
 				.renderAsHtml(mediaBaseUrl), 4, -1, true, baseContainer, null, masteryEditLayout, ureq.getUserSession(), getWindowControl());
 		FormLink editLink = uifactory.addFormLink("editLink", masteryEditLayout, Link.NONTRANSLATED + Link.LINK_CUSTOM_CSS);
-		((Link) editLink.getComponent()).setCustomDisplayText(" ");
-		((Link) editLink.getComponent()).setIconLeftCSS("o_icon o_icon_edit o_icon-lg qti_edit_link");
+		editLink.getComponent().setCustomDisplayText(" ");
+		editLink.getComponent().setIconLeftCSS("o_icon o_icon_edit o_icon-lg qti_edit_link");
 		registerFeedbackElement(masteryMat, masteryFeedback, editLink);
 
 		// One Failure Layout
@@ -239,8 +239,8 @@ public class FeedbackFormController extends FormBasicController {
 				.renderAsHtml(mediaBaseUrl), 4, -1, true, baseContainer, null, failureEditLayout, ureq.getUserSession(), getWindowControl());
 		failureFeedback.setLabel("item_feedback_fail", null);
 		FormLink failureLink = uifactory.addFormLink("editLink", failureEditLayout, Link.NONTRANSLATED + Link.LINK_CUSTOM_CSS);
-		((Link) failureLink.getComponent()).setCustomDisplayText("");
-		((Link) failureLink.getComponent()).setIconLeftCSS("o_icon o_icon_edit o_icon-lg");
+		failureLink.getComponent().setCustomDisplayText("");
+		failureLink.getComponent().setIconLeftCSS("o_icon o_icon_edit o_icon-lg");
 		registerFeedbackElement(failureMat, failureFeedback, failureLink);
 
 		// Feedback for each response when single or multiple choice question
@@ -258,8 +258,8 @@ public class FeedbackFormController extends FormBasicController {
 						.renderAsHtml(mediaBaseUrl), 4, -1, true, baseContainer, null, responseLevelHintsLayout, ureq.getUserSession(),
 						getWindowControl());
 				FormLink link = uifactory.addFormLink("link_" + i, responseLevelHintsLayout, Link.NONTRANSLATED + Link.LINK_CUSTOM_CSS);
-				((Link) link.getComponent()).setCustomDisplayText(" ");
-				((Link) link.getComponent()).setIconLeftCSS("o_icon o_icon_edit o_icon-lg");
+				link.getComponent().setCustomDisplayText(" ");
+				link.getComponent().setIconLeftCSS("o_icon o_icon_edit o_icon-lg");
 				registerFeedbackElement(responseFeedbackMat, responseHintText, link);
 				// get response for displaying
 				Material responseMat = response.getContent();
diff --git a/src/main/java/org/olat/modules/portfolio/BinderSecurityCallback.java b/src/main/java/org/olat/modules/portfolio/BinderSecurityCallback.java
index e0fe1c9180b..7a55a1791f9 100644
--- a/src/main/java/org/olat/modules/portfolio/BinderSecurityCallback.java
+++ b/src/main/java/org/olat/modules/portfolio/BinderSecurityCallback.java
@@ -84,6 +84,8 @@ public interface BinderSecurityCallback {
 	
 	public boolean canViewElement(PortfolioElement element);
 	
+	public boolean canViewPendingAssignments(Section section);
+	
 	public boolean canViewEmptySection(Section section);
 	
 	public boolean canComment(PortfolioElement element);
diff --git a/src/main/java/org/olat/modules/portfolio/BinderSecurityCallbackFactory.java b/src/main/java/org/olat/modules/portfolio/BinderSecurityCallbackFactory.java
index d8956c34856..43afefd9e13 100644
--- a/src/main/java/org/olat/modules/portfolio/BinderSecurityCallbackFactory.java
+++ b/src/main/java/org/olat/modules/portfolio/BinderSecurityCallbackFactory.java
@@ -180,6 +180,11 @@ public class BinderSecurityCallbackFactory {
 		public boolean canViewElement(PortfolioElement element) {
 			return true;
 		}
+
+		@Override
+		public boolean canViewPendingAssignments(Section section) {
+			return true;
+		}
 	}
 	
 	private static class BinderSecurityCallbackImpl implements BinderSecurityCallback {
@@ -403,6 +408,22 @@ public class BinderSecurityCallbackFactory {
 			return false;
 		}
 
+		@Override
+		public boolean canViewPendingAssignments(Section section) {
+			if(owner) return true;
+			
+			if(rights != null) {
+				for(AccessRights right:rights) {
+					if((PortfolioRoles.reviewer.equals(right.getRole()) || PortfolioRoles.coach.equals(right.getRole()))
+							&& right.matchElementAndAncestors(section)) {
+						return true;
+					}
+				}
+			}
+
+			return false;
+		}
+
 		@Override
 		public boolean canComment(PortfolioElement element) {
 			if(element.getType() == PortfolioElementType.page) {
@@ -542,6 +563,11 @@ public class BinderSecurityCallbackFactory {
 			return false;
 		}
 
+		@Override
+		public boolean canViewPendingAssignments(Section section) {
+			return false;
+		}
+
 		@Override
 		public boolean canViewEmptySection(Section section) {
 			return false;
diff --git a/src/main/java/org/olat/modules/portfolio/ui/AssignmentEditController.java b/src/main/java/org/olat/modules/portfolio/ui/AssignmentEditController.java
index df8845e0cee..1f4b434c556 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/AssignmentEditController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/AssignmentEditController.java
@@ -73,7 +73,8 @@ public class AssignmentEditController extends FormBasicController {
 			AssignmentType.essay.name(), AssignmentType.document.name()
 	};
 	
-	private TextElement titleEl, summaryEl;
+	private TextElement titleEl;
+	private RichTextElement summaryEl;
 	//private SingleSelection typeEl;
 	private FileElement documentUploadEl;
 	private FormLayoutContainer filesLayout;
@@ -115,13 +116,15 @@ public class AssignmentEditController extends FormBasicController {
 		titleEl.setMandatory(true);
 		
 		String summary = assignment == null ? null : assignment.getSummary();
-		summaryEl = uifactory.addTextAreaElement("summary", "summary", 4096, 6, 60, false, summary, formLayout);
+		summaryEl = uifactory.addRichTextElementForStringDataMinimalistic("summary", "summary", summary, 8, 60, formLayout, getWindowControl());
 		summaryEl.setElementCssClass("o_sel_pf_edit_assignment_summary");
 		summaryEl.setPlaceholderKey("summary.placeholder", null);
+		summaryEl.getEditorConfiguration().setStatusBar(false);
 		
 		String content = assignment == null ? null : assignment.getContent();
 		contentEl = uifactory.addRichTextElementForStringDataCompact("content", "assignment.content", content, 6, 60, null, formLayout,
 				ureq.getUserSession(), getWindowControl());
+		contentEl.setElementCssClass("o_sel_pf_edit_assignment_content");
 		contentEl.getEditorConfiguration().disableMedia();
 		contentEl.getEditorConfiguration().disableImageAndMovie();
 		/*
diff --git a/src/main/java/org/olat/modules/portfolio/ui/BinderMetadataEditController.java b/src/main/java/org/olat/modules/portfolio/ui/BinderMetadataEditController.java
index 93854268118..26b95ca606e 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/BinderMetadataEditController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/BinderMetadataEditController.java
@@ -30,6 +30,7 @@ import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FileElement;
+import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
 import org.olat.core.gui.components.form.flexible.elements.TextBoxListElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
@@ -66,7 +67,8 @@ public class BinderMetadataEditController extends FormBasicController {
 		imageMimeTypes.add("image/png");
 	}
 	
-	private TextElement titleEl, summaryEl;
+	private TextElement titleEl;
+	private RichTextElement summaryEl;
 	private TextBoxListElement categoriesEl;
 	
 	private FileElement fileUpload;
@@ -109,9 +111,10 @@ public class BinderMetadataEditController extends FormBasicController {
 		titleEl.setMandatory(true);
 		
 		String summary = binder == null ? null : binder.getSummary();
-		summaryEl = uifactory.addTextAreaElement("summary", "summary", 4096, 4, 60, false, summary, formLayout);
+		summaryEl = uifactory.addRichTextElementForStringDataMinimalistic("summary", "summary", summary, 8, 60, formLayout, getWindowControl());
 		summaryEl.setElementCssClass("o_sel_pf_edit_binder_summary");
 		summaryEl.setPlaceholderKey("summary.placeholder", null);
+		summaryEl.getEditorConfiguration().setStatusBar(false);
 		
 		fileUpload = uifactory.addFileElement(getWindowControl(), "file", "fileupload",formLayout);			
 		fileUpload.setPreview(ureq.getUserSession(), true);
diff --git a/src/main/java/org/olat/modules/portfolio/ui/BinderPageListController.java b/src/main/java/org/olat/modules/portfolio/ui/BinderPageListController.java
index 0453bc9515d..d767f75b437 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/BinderPageListController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/BinderPageListController.java
@@ -197,8 +197,8 @@ public class BinderPageListController extends AbstractPageListController {
 		}
 		
 		for(Assignment assignment:assignments) {
-			if(assignment.getPage() == null) {
-				Section section = assignment.getSection();
+			Section section = assignment.getSection();
+			if(assignment.getPage() == null && secCallback.canViewPendingAssignments(section)) {
 				List<Assignment> sectionAssignments = sectionToAssignmentMap.get(section);
 				PortfolioElementRow row = forgePendingAssignmentRow(assignment, section, sectionAssignments);
 				rows.add(row);
diff --git a/src/main/java/org/olat/modules/portfolio/ui/BinderPickerController.java b/src/main/java/org/olat/modules/portfolio/ui/BinderPickerController.java
index 1826e4b0d38..dd9ccc8d31b 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/BinderPickerController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/BinderPickerController.java
@@ -161,7 +161,7 @@ public class BinderPickerController extends FormBasicController {
 
 	private void updateSelectedBinderUI() {
 		String copyTitle = StringHelper.escapeHtml(copyBinder.getTitle());
-		((Link)selectMapLink.getComponent()).setCustomDisplayText(copyTitle);
+		selectMapLink.getComponent().setCustomDisplayText(copyTitle);
 		
 		updateCopyDate(copyBinder.getCopyDate());
 		updateAssessmentInfos(copyBinder.getReturnDate());
diff --git a/src/main/java/org/olat/modules/portfolio/ui/MediaUploadController.java b/src/main/java/org/olat/modules/portfolio/ui/MediaUploadController.java
index 4b391d27602..69267aafa73 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/MediaUploadController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/MediaUploadController.java
@@ -29,6 +29,7 @@ import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FileElement;
+import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
 import org.olat.core.gui.components.form.flexible.elements.TextBoxListElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
@@ -61,7 +62,7 @@ public class MediaUploadController extends FormBasicController implements PageEl
 	
 	private FileElement fileEl;
 	private TextElement titleEl;
-	private TextElement descriptionEl;
+	private RichTextElement descriptionEl;
 	private TextBoxListElement categoriesEl;
 
 	private Media mediaReference;
@@ -106,7 +107,8 @@ public class MediaUploadController extends FormBasicController implements PageEl
 		titleEl = uifactory.addTextElement("artefact.title", "artefact.title", 255, "", formLayout);
 		titleEl.setMandatory(true);
 		
-		descriptionEl = uifactory.addRichTextElementForStringData("artefact.descr", "artefact.descr", "", 8, 6, false, null, null, formLayout, ureq.getUserSession(), getWindowControl());
+		descriptionEl = uifactory.addRichTextElementForStringDataMinimalistic("artefact.descr", "artefact.descr", "", 8, 60, formLayout, getWindowControl());
+		descriptionEl.getEditorConfiguration().setStatusBar(false);
 		
 		fileEl = uifactory.addFileElement(getWindowControl(), "artefact.file", "artefact.file", formLayout);
 		fileEl.addActionListener(FormEvent.ONCHANGE);
diff --git a/src/main/java/org/olat/modules/portfolio/ui/PageMetadataEditController.java b/src/main/java/org/olat/modules/portfolio/ui/PageMetadataEditController.java
index b0858348bde..ee8f2139d32 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/PageMetadataEditController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/PageMetadataEditController.java
@@ -30,6 +30,7 @@ import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FileElement;
+import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
 import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
 import org.olat.core.gui.components.form.flexible.elements.TextBoxListElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
@@ -69,7 +70,8 @@ public class PageMetadataEditController extends FormBasicController {
 	
 	private static final String[] alignKeys = new String[]{ PageImageAlign.background.name(), PageImageAlign.right.name() };
 	
-	private TextElement titleEl, summaryEl;
+	private TextElement titleEl;
+	private RichTextElement summaryEl;
 	private SingleSelection bindersEl, sectionsEl;
 	private TextBoxListElement categoriesEl;
 	
@@ -151,10 +153,11 @@ public class PageMetadataEditController extends FormBasicController {
 		titleEl.setMandatory(true);
 		
 		String summary = page == null ? null : page.getSummary();
-		summaryEl = uifactory.addTextAreaElement("summary", "page.summary", 4096, 4, 60, false, summary, formLayout);
+		summaryEl = uifactory.addRichTextElementForStringDataMinimalistic("summary", "page.summary", summary, 8, 60, formLayout, getWindowControl());
 		summaryEl.setPlaceholderKey("summary.placeholder", null);
 		summaryEl.setEnabled(editTitleAndSummary);
-		
+		summaryEl.getEditorConfiguration().setStatusBar(false);
+
 		imageUpload = uifactory.addFileElement(getWindowControl(), "file", "fileupload",formLayout);			
 		imageUpload.setPreview(ureq.getUserSession(), true);
 		imageUpload.addActionListener(FormEvent.ONCHANGE);
diff --git a/src/main/java/org/olat/modules/portfolio/ui/PageRunController.java b/src/main/java/org/olat/modules/portfolio/ui/PageRunController.java
index c3ad9f82f6d..ac8d443295b 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/PageRunController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/PageRunController.java
@@ -103,6 +103,7 @@ public class PageRunController extends BasicController implements TooledControll
 	private Page page;
 	private List<Assignment> assignments;
 	private boolean dirtyMarker = false;
+	private final boolean openInEditMode;
 	private final BinderSecurityCallback secCallback;
 	
 	@Autowired
@@ -114,6 +115,7 @@ public class PageRunController extends BasicController implements TooledControll
 		this.page = page;
 		this.stackPanel = stackPanel;
 		this.secCallback = secCallback;
+		this.openInEditMode = openInEditMode;
 		
 		assignments = portfolioService.getAssignments(page);
 		
@@ -138,9 +140,7 @@ public class PageRunController extends BasicController implements TooledControll
 
 	@Override
 	public void initTools() {
-		editLink = LinkFactory.createToolLink("edit.page", translate("edit.page"), this);
-		editLink.setIconLeftCSS("o_icon o_icon-lg o_icon_edit");
-		editLink.setVisible(secCallback.canEditPage(page));
+		editLink(!openInEditMode);
 		stackPanel.addTool(editLink, Align.left);
 
 		editMetadataLink = LinkFactory.createToolLink("edit.page.metadata", translate("edit.page.metadata"), this);
@@ -148,12 +148,28 @@ public class PageRunController extends BasicController implements TooledControll
 		editMetadataLink.setVisible(secCallback.canEditMetadataBinder());
 		stackPanel.addTool(editMetadataLink, Align.left);
 		
-		deleteLink = LinkFactory.createToolLink("edit.page", translate("delete.page"), this);
+		deleteLink = LinkFactory.createToolLink("delete.page", translate("delete.page"), this);
 		deleteLink.setIconLeftCSS("o_icon o_icon-lg o_icon_delete_item");
 		deleteLink.setVisible(secCallback.canDeletePage(page));
 		stackPanel.addTool(deleteLink, Align.right);
 	}
 	
+	private Link editLink(boolean edit) {
+		if(editLink == null) {
+			editLink = LinkFactory.createToolLink("edit.page", translate("edit.page"), this);
+		}
+		if(edit) {
+			editLink.setCustomDisplayText(translate("edit.page"));
+			editLink.setIconLeftCSS("o_icon o_icon-lg o_icon_toggle_on");
+		} else {
+			editLink.setCustomDisplayText(translate("edit.page.close"));
+			editLink.setIconLeftCSS("o_icon o_icon-lg o_icon_toggle_off");
+		}
+		editLink.setVisible(secCallback.canEditPage(page));
+		editLink.setUserObject(edit);
+		return editLink;
+	}
+	
 	private void loadModel(UserRequest ureq) {
 		mainVC.contextPut("pageTitle", page.getTitle());
 		pageCtrl.loadElements(ureq);
@@ -371,16 +387,13 @@ public class PageRunController extends BasicController implements TooledControll
 	
 	private void doEditPage(UserRequest ureq) {
 		removeAsListenerAndDispose(pageEditCtrl);
-		if(Boolean.TRUE.equals(editLink.getUserObject())) {
+		if(Boolean.FALSE.equals(editLink.getUserObject())) {
 			doRunPage(ureq);
 		} else {
 			pageEditCtrl = new PageEditorController(ureq, getWindowControl(), new PortfolioPageEditorProvider());
 			listenTo(pageEditCtrl);
 			mainVC.put("page", pageEditCtrl.getInitialComponent());
-			
-			editLink.setCustomDisplayText(translate("save"));
-			editLink.setIconLeftCSS("o_icon o_icon-lg o_icon_save");
-			editLink.setUserObject(Boolean.TRUE);
+			editLink(false);
 		}
 	}
 	
@@ -389,11 +402,7 @@ public class PageRunController extends BasicController implements TooledControll
 			loadModel(ureq);
 		}
 		mainVC.put("page", pageCtrl.getInitialComponent());
-		if(editLink != null) {
-			editLink.setCustomDisplayText(translate("edit.page"));
-			editLink.setIconLeftCSS("o_icon o_icon-lg o_icon_edit");
-			editLink.setUserObject(Boolean.FALSE);
-		}
+		editLink(true);
 	}
 
 	private class PortfolioPageProvider implements PageProvider {
diff --git a/src/main/java/org/olat/modules/portfolio/ui/SectionEditController.java b/src/main/java/org/olat/modules/portfolio/ui/SectionEditController.java
index 292b657feb7..aede8ba513d 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/SectionEditController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/SectionEditController.java
@@ -24,6 +24,7 @@ import java.util.Date;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.DateChooser;
+import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
@@ -44,7 +45,8 @@ import org.springframework.beans.factory.annotation.Autowired;
  */
 public class SectionEditController extends FormBasicController {
 
-	private TextElement titleEl, descriptionEl;
+	private TextElement titleEl;
+	private RichTextElement descriptionEl;
 	private DateChooser beginDateEl, endDateEl;
 	
 	private BinderRef binder;
@@ -94,8 +96,9 @@ public class SectionEditController extends FormBasicController {
 		titleEl.setMandatory(true);
 		
 		String description = section == null ? null : section.getDescription();
-		descriptionEl = uifactory.addTextAreaElement("summary", "summary", 4096, 4, 60, false, description, formLayout);
+		descriptionEl = uifactory.addRichTextElementForStringDataMinimalistic("summary", "page.summary", description, 8, 60, formLayout, getWindowControl());
 		descriptionEl.setPlaceholderKey("summary.placeholder", null);
+		descriptionEl.getEditorConfiguration().setStatusBar(false);
 		
 		Date begin = section == null ? null : section.getBeginDate();
 		beginDateEl = uifactory.addDateChooser("begin.date", "begin.date", begin, formLayout);
diff --git a/src/main/java/org/olat/modules/portfolio/ui/TableOfContentController.java b/src/main/java/org/olat/modules/portfolio/ui/TableOfContentController.java
index e9e93416bc1..6fc869e9fcc 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/TableOfContentController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/TableOfContentController.java
@@ -186,18 +186,21 @@ public class TableOfContentController extends BasicController implements TooledC
 			boolean first = count == 0;
 			boolean last = count == sections.size() - 1;
 			count++;
-			SectionRow sectionRow = forgeSectionRow(section,
-					sectionToAssessmentSectionMap.get(section),
-					sectionToAssignmentMap.get(section),
-					first, last);
-			sectionList.add(sectionRow);
-			sectionMap.put(section.getKey(), sectionRow);
+			
+			if(secCallback.canViewElement(section)) {
+				SectionRow sectionRow = forgeSectionRow(section,
+						sectionToAssessmentSectionMap.get(section),
+						sectionToAssignmentMap.get(section),
+						first, last);
+				sectionList.add(sectionRow);
+				sectionMap.put(section.getKey(), sectionRow);
+			}
 		}
 
 		List<Page> pages = portfolioService.getPages(binder, null);
 		for(Page page:pages) {
-			if(secCallback.canViewElement(page)) {
-				Section section = page.getSection();
+			Section section = page.getSection();
+			if(secCallback.canViewElement(page) && section != null) {
 				SectionRow sectionRow = sectionMap.get(section.getKey());
 				PageRow pageRow = forgePageRow(page, numberOfCommentsMap);
 				sectionRow.getPages().add(pageRow);
@@ -219,10 +222,12 @@ public class TableOfContentController extends BasicController implements TooledC
 		String title = StringHelper.escapeHtml(section.getTitle());
 		
 		List<Assignment> notAssignedAssignments = new ArrayList<>();
-		if(assignemnts != null) {
-			for(Assignment assignemnt:assignemnts) {
-				if(assignemnt.getPage() == null) {
-					notAssignedAssignments.add(assignemnt);
+		if(secCallback.canViewPendingAssignments(section)) {
+			if(assignemnts != null) {
+				for(Assignment assignemnt:assignemnts) {
+					if(assignemnt.getPage() == null) {
+						notAssignedAssignments.add(assignemnt);
+					}
 				}
 			}
 		}
diff --git a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_de.properties
index cb58ae61e0c..9b8dcd99245 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_de.properties
@@ -105,7 +105,8 @@ edit.assignment=Aufgabe bearbeiten
 edit.binder.metadata=Metadaten bearbeiten
 edit.last.binder=Letzte benutzte Sammelmappe \u00F6ffnen
 edit.last.entry=Letzten Eintrag bearbeiten
-edit.page=Eintrag bearbeiten
+edit.page=Editor öffnen
+edit.page.close=Editor schliessen
 edit.page.metadata=Metadaten bearbeiten
 edition=Edition
 end.date=Enddatum
diff --git a/src/main/java/org/olat/modules/portfolio/ui/component/CitationComponentRenderer.java b/src/main/java/org/olat/modules/portfolio/ui/component/CitationComponentRenderer.java
index f7a7ac25e5f..3ff7bb968cf 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/component/CitationComponentRenderer.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/component/CitationComponentRenderer.java
@@ -48,7 +48,7 @@ public class CitationComponentRenderer extends DefaultComponentRenderer {
 	
 	public static void renderAPAGerman(StringOutput sb, Citation citation, DublinCoreMetadata dcData, String notes, String links) {
 		String authors = dcData.getCreators();		
-		String authorString = getAuthors(authors, " (Hrsg.). ", true);
+		String authorString = getAuthors(authors/* " (Hrsg.). ", true*/);
 		String edition = getOrdinalAPA(citation.getEdition());
 		String volume = getVolumeAPA(citation.getVolume());
 		String series = getSeries(citation.getSeries());
@@ -105,7 +105,7 @@ public class CitationComponentRenderer extends DefaultComponentRenderer {
 		sb.append("</div>");
 	}
 	
-	public static String getAuthors(String authors, String d, boolean apa) {
+	public static String getAuthors(String authors/*, String d, boolean apa*/) {
 		//TODO portfolio
 		return authors;
 	}
diff --git a/src/main/java/org/olat/modules/portfolio/ui/component/TimelineComponentRenderer.java b/src/main/java/org/olat/modules/portfolio/ui/component/TimelineComponentRenderer.java
index eaa3766976e..b512ca7bcf5 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/component/TimelineComponentRenderer.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/component/TimelineComponentRenderer.java
@@ -27,6 +27,7 @@ import org.olat.core.gui.render.Renderer;
 import org.olat.core.gui.render.StringOutput;
 import org.olat.core.gui.render.URLBuilder;
 import org.olat.core.gui.translator.Translator;
+import org.olat.core.util.StringHelper;
 
 /**
  * 
@@ -70,7 +71,7 @@ public class TimelineComponentRenderer extends DefaultComponentRenderer {
 				TimelinePoint point = cmp.getPoints().get(i);
 				if(i > 0) sb.append(",");
 				sb.append("{ id:\"").append(point.getId()).append("\"")
-				  .append(", \"title\":").append(JSONObject.quote(point.getTitle()))
+				  .append(", \"title\":").append(JSONObject.quote(StringHelper.escapeHtml(point.getTitle())))
 				  .append(", \"time\":").append(point.getDate().getTime()).append("")
 				  .append(", \"status\":\"").append(point.getStatus()).append("\"}");
 			}
diff --git a/src/main/java/org/olat/modules/portfolio/ui/media/CollectCitationMediaController.java b/src/main/java/org/olat/modules/portfolio/ui/media/CollectCitationMediaController.java
index 97aece6a19e..14fea18e769 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/media/CollectCitationMediaController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/media/CollectCitationMediaController.java
@@ -29,6 +29,7 @@ import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.DateChooser;
+import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
 import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
 import org.olat.core.gui.components.form.flexible.elements.TextBoxListElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
@@ -74,7 +75,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 public class CollectCitationMediaController extends FormBasicController implements PageElementAddController {
 	
 	private TextElement titleEl;
-	private TextElement descriptionEl, textEl;
+	private RichTextElement descriptionEl, textEl;
 	private TextBoxListElement categoriesEl;
 	
 	private SingleSelection sourceTypeEl;
@@ -147,7 +148,8 @@ public class CollectCitationMediaController extends FormBasicController implemen
 		titleEl.setMandatory(true);
 		
 		String desc = mediaReference == null ? null : mediaReference.getDescription();
-		descriptionEl = uifactory.addRichTextElementForStringData("artefact.descr", "artefact.descr", desc, 6, 6, false, null, null, formLayout, ureq.getUserSession(), getWindowControl());
+		descriptionEl = uifactory.addRichTextElementForStringDataMinimalistic("artefact.descr", "artefact.descr", desc, 6, 60, formLayout, getWindowControl());
+		descriptionEl.getEditorConfiguration().setStatusBar(false);
 		
 		String text = mediaReference == null ? null : mediaReference.getContent();
 		textEl = uifactory.addRichTextElementForStringData("citation", "citation", text, 10, 6, false, null, null, formLayout, ureq.getUserSession(), getWindowControl());
diff --git a/src/main/java/org/olat/modules/portfolio/ui/media/CollectFileMediaController.java b/src/main/java/org/olat/modules/portfolio/ui/media/CollectFileMediaController.java
index 3f449a3f659..1149f3890a1 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/media/CollectFileMediaController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/media/CollectFileMediaController.java
@@ -28,6 +28,7 @@ import java.util.Map;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FileElement;
+import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
 import org.olat.core.gui.components.form.flexible.elements.TextBoxListElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
@@ -63,7 +64,7 @@ public class CollectFileMediaController extends FormBasicController implements P
 	
 	private FileElement fileEl;
 	private TextElement titleEl;
-	private TextElement descriptionEl;
+	private RichTextElement descriptionEl;
 	private TextBoxListElement categoriesEl;
 
 	private Media mediaReference;
@@ -125,7 +126,8 @@ public class CollectFileMediaController extends FormBasicController implements P
 		titleEl.setMandatory(true);
 		
 		String desc = mediaReference == null ? null : mediaReference.getTitle();
-		descriptionEl = uifactory.addRichTextElementForStringData("artefact.descr", "artefact.descr", desc, 8, 6, false, null, null, formLayout, ureq.getUserSession(), getWindowControl());
+		descriptionEl = uifactory.addRichTextElementForStringDataMinimalistic("artefact.descr", "artefact.descr", desc, 8, 60, formLayout, getWindowControl());
+		descriptionEl.getEditorConfiguration().setStatusBar(false);
 		
 		fileEl = uifactory.addFileElement(getWindowControl(), "artefact.file", "artefact.file", formLayout);
 		fileEl.addActionListener(FormEvent.ONCHANGE);
diff --git a/src/main/java/org/olat/modules/portfolio/ui/media/CollectImageMediaController.java b/src/main/java/org/olat/modules/portfolio/ui/media/CollectImageMediaController.java
index 9c58df6bff4..77c56b77c9a 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/media/CollectImageMediaController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/media/CollectImageMediaController.java
@@ -28,6 +28,7 @@ import java.util.Map;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FileElement;
+import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
 import org.olat.core.gui.components.form.flexible.elements.TextBoxListElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
@@ -63,7 +64,7 @@ public class CollectImageMediaController extends FormBasicController implements
 	
 	private FileElement fileEl;
 	private TextElement titleEl;
-	private TextElement descriptionEl;
+	private RichTextElement descriptionEl;
 	private TextBoxListElement categoriesEl;
 
 	private Media mediaReference;
@@ -125,7 +126,8 @@ public class CollectImageMediaController extends FormBasicController implements
 		titleEl.setMandatory(true);
 		
 		String desc = mediaReference == null ? null : mediaReference.getDescription();
-		descriptionEl = uifactory.addRichTextElementForStringData("artefact.descr", "artefact.descr", desc, 8, 6, false, null, null, formLayout, ureq.getUserSession(), getWindowControl());
+		descriptionEl = uifactory.addRichTextElementForStringDataMinimalistic("artefact.descr", "artefact.descr", desc, 8, 60, formLayout, getWindowControl());
+		descriptionEl.getEditorConfiguration().setStatusBar(false);
 		
 		fileEl = uifactory.addFileElement(getWindowControl(), "artefact.file", "artefact.file", formLayout);
 		fileEl.addActionListener(FormEvent.ONCHANGE);
diff --git a/src/main/java/org/olat/modules/portfolio/ui/media/CollectTextMediaController.java b/src/main/java/org/olat/modules/portfolio/ui/media/CollectTextMediaController.java
index b2492da3d10..de01745e0ae 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/media/CollectTextMediaController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/media/CollectTextMediaController.java
@@ -26,6 +26,7 @@ import java.util.Map;
 
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
 import org.olat.core.gui.components.form.flexible.elements.TextBoxListElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
@@ -57,7 +58,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 public class CollectTextMediaController extends FormBasicController implements PageElementAddController {
 	
 	private TextElement titleEl;
-	private TextElement descriptionEl, textEl;
+	private RichTextElement descriptionEl, textEl;
 	private TextBoxListElement categoriesEl;
 
 	private Media mediaReference;
@@ -120,7 +121,8 @@ public class CollectTextMediaController extends FormBasicController implements P
 		titleEl.setMandatory(true);
 		
 		String desc = mediaReference == null ? null : mediaReference.getDescription();
-		descriptionEl = uifactory.addRichTextElementForStringData("artefact.descr", "artefact.descr", desc, 6, 6, false, null, null, formLayout, ureq.getUserSession(), getWindowControl());
+		descriptionEl = uifactory.addRichTextElementForStringDataMinimalistic("artefact.descr", "artefact.descr", desc, 6, 60, formLayout, getWindowControl());
+		descriptionEl.getEditorConfiguration().setStatusBar(false);
 		
 		String content = mediaReference == null ? null : mediaReference.getContent();
 		textEl = uifactory.addRichTextElementForStringData("artefact.text", "artefact.text", content, 10, 6, false, null, null, formLayout, ureq.getUserSession(), getWindowControl());
diff --git a/src/main/java/org/olat/modules/portfolio/ui/media/CollectVideoMediaController.java b/src/main/java/org/olat/modules/portfolio/ui/media/CollectVideoMediaController.java
index 689561f074d..2231c97fe3a 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/media/CollectVideoMediaController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/media/CollectVideoMediaController.java
@@ -28,6 +28,7 @@ import java.util.Map;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FileElement;
+import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
 import org.olat.core.gui.components.form.flexible.elements.TextBoxListElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
@@ -63,7 +64,7 @@ public class CollectVideoMediaController extends FormBasicController implements
 	
 	private FileElement fileEl;
 	private TextElement titleEl;
-	private TextElement descriptionEl;
+	private RichTextElement descriptionEl;
 	private TextBoxListElement categoriesEl;
 
 	private Media mediaReference;
@@ -126,7 +127,8 @@ public class CollectVideoMediaController extends FormBasicController implements
 		titleEl.setMandatory(true);
 		
 		String desc = mediaReference == null ? null : mediaReference.getDescription();
-		descriptionEl = uifactory.addRichTextElementForStringData("artefact.descr", "artefact.descr", desc, 8, 6, false, null, null, formLayout, ureq.getUserSession(), getWindowControl());
+		descriptionEl = uifactory.addRichTextElementForStringDataMinimalistic("artefact.descr", "artefact.descr", desc, 8, 60, formLayout, getWindowControl());
+		descriptionEl.getEditorConfiguration().setStatusBar(false);
 		
 		fileEl = uifactory.addFileElement(getWindowControl(), "artefact.file", "artefact.file", formLayout);
 		fileEl.addActionListener(FormEvent.ONCHANGE);
diff --git a/src/main/java/org/olat/modules/portfolio/ui/media/_content/media_citation.html b/src/main/java/org/olat/modules/portfolio/ui/media/_content/media_citation.html
index f15a92af034..28cbdfc6717 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/media/_content/media_citation.html
+++ b/src/main/java/org/olat/modules/portfolio/ui/media/_content/media_citation.html
@@ -2,7 +2,7 @@
 	#if($r.available("cit"))
 		$r.render("cit")
 	#else
-	<div class="o_quote_author">$author</div>
+	<div class="o_quote_author">$r.escapeHtml($author)</div>
 	#end
 	<blockquote class="o_quote">$r.xssScan($citation)</blockquote>
 </div>
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/portfolio/ui/model/PortfolioElementRow.java b/src/main/java/org/olat/modules/portfolio/ui/model/PortfolioElementRow.java
index 9922c967e7e..770eb5fa006 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/model/PortfolioElementRow.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/model/PortfolioElementRow.java
@@ -300,7 +300,7 @@ public class PortfolioElementRow {
 
 	public String[] getMetaBinderAndSectionTitles() {
 		if(StringHelper.containsNonWhitespace(metaBinderTitle) && StringHelper.containsNonWhitespace(metaSectionTitle)) {
-			return new String[]{ metaBinderTitle, metaSectionTitle };
+			return new String[]{ StringHelper.escapeHtml(metaBinderTitle), StringHelper.escapeHtml(metaSectionTitle) };
 		}
 		return null;
 	}
diff --git a/src/main/java/org/olat/search/ui/SearchInputController.java b/src/main/java/org/olat/search/ui/SearchInputController.java
index 7d6c247e6a4..8742baa6e44 100644
--- a/src/main/java/org/olat/search/ui/SearchInputController.java
+++ b/src/main/java/org/olat/search/ui/SearchInputController.java
@@ -243,7 +243,7 @@ public class SearchInputController extends FormBasicController implements Generi
 		if(!context.isEmpty()) {
 			String scope = context.getValueAt(context.getSize() - 1);
 			String tooltip = getTranslator().translate("form.search.label.tooltip", new String[]{scope});
-			((Link)searchButton.getComponent()).setTooltip(tooltip);
+			searchButton.getComponent().setTooltip(tooltip);
 		}
 	}
 	
diff --git a/src/test/java/org/olat/selenium/PortfolioV2Test.java b/src/test/java/org/olat/selenium/PortfolioV2Test.java
index b2a52fb6e9f..150cb23195f 100644
--- a/src/test/java/org/olat/selenium/PortfolioV2Test.java
+++ b/src/test/java/org/olat/selenium/PortfolioV2Test.java
@@ -148,7 +148,7 @@ public class PortfolioV2Test {
 			.assertOnBinder()
 			.selectEntries()
 			.createSectionInEntries(sectionTitle)
-			.createAssignmentForSection(sectionTitle, assignmentTitle, "Write a small text")
+			.createAssignmentForSection(sectionTitle, assignmentTitle, "Write a small summary", "Your task is...")
 			.assertOnAssignmentInEntries(assignmentTitle);
 		
 		String courseTitle = "PF Course " + UUID.randomUUID();
diff --git a/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java b/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java
index 05dc10b449d..5c6f78fded1 100644
--- a/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java
+++ b/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java
@@ -90,6 +90,17 @@ public class OOGraphene {
 		((JavascriptExecutor)browser).executeScript("top.tinymce.activeEditor.setContent('" + content + "')");
 	}
 	
+	public static final void tinymce(String content, String containerCssSelector, WebDriver browser) {
+		By tinyIdBy = By.cssSelector(containerCssSelector + " div.o_richtext_mce");
+		waitElement(tinyIdBy, 5, browser);
+		WebElement tinyIdEl = browser.findElement(tinyIdBy);
+		String tinyId = tinyIdEl.getAttribute("id").replace("_diw", "");
+
+		Graphene.waitModel(browser).withTimeout(waitTinyDuration, TimeUnit.SECONDS)
+			.pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until(new TinyMCELoadedByIdPredicate(tinyId));
+		((JavascriptExecutor)browser).executeScript("top.tinymce.editors['" + tinyId + "'].setContent('" + content + "')");
+	}
+	
 	/**
 	 * Make sure that the checkbox is in the correct state.
 	 * @param checkboxEl
diff --git a/src/test/java/org/olat/selenium/page/graphene/TinyMCELoadedByIdPredicate.java b/src/test/java/org/olat/selenium/page/graphene/TinyMCELoadedByIdPredicate.java
new file mode 100644
index 00000000000..a8871d9eb31
--- /dev/null
+++ b/src/test/java/org/olat/selenium/page/graphene/TinyMCELoadedByIdPredicate.java
@@ -0,0 +1,52 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.selenium.page.graphene;
+
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebDriver;
+
+import com.google.common.base.Predicate;
+
+/**
+ * Predicate which test if TinyMCE is fully loaded and specifically
+ * the tiny with the specified id.
+ * 
+ * Initial date: 06.09.2016<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class TinyMCELoadedByIdPredicate implements Predicate<WebDriver> {
+	
+	private final String id;
+	
+	public TinyMCELoadedByIdPredicate(String id) {
+		this.id = id;
+	}
+	
+	@Override
+	public boolean apply(WebDriver driver) {
+        Object active = ((JavascriptExecutor)driver)
+        		.executeScript("return top != null && top.tinymce != null && top.tinymce.activeEditor != null "
+        				+ " && top.tinymce.activeEditor.initialized && top.tinymce.editors[0].initialized "
+        				+ " && (top.tinymce.editors.length > 1 ? top.tinymce.editors[1].initialized : true)"
+        				+ " && top.tinymce.editors['" + id + "'].initialized;");
+        return Boolean.TRUE.equals(active);
+    }
+}
diff --git a/src/test/java/org/olat/selenium/page/portfolio/BinderPage.java b/src/test/java/org/olat/selenium/page/portfolio/BinderPage.java
index 3135be62aef..0d15f92dd0f 100644
--- a/src/test/java/org/olat/selenium/page/portfolio/BinderPage.java
+++ b/src/test/java/org/olat/selenium/page/portfolio/BinderPage.java
@@ -172,7 +172,7 @@ public class BinderPage {
 		return this;
 	}
 	
-	public BinderPage createAssignmentForSection(String sectionTitle, String title, String summary) {
+	public BinderPage createAssignmentForSection(String sectionTitle, String title, String summary, String content) {
 		By newAssignmentBy = By.xpath("//div[contains(@class,'o_portfolio_section')][h3[contains(text(),'" + sectionTitle + "')]]//a[contains(@class,'o_sel_pf_new_assignment')]");
 		List<WebElement> newAssignmentButtons = browser.findElements(newAssignmentBy);
 		Assert.assertEquals(1, newAssignmentButtons.size());
@@ -187,9 +187,8 @@ public class BinderPage {
 		By nameBy = By.cssSelector(".o_sel_pf_edit_assignment_title input[type='text']");
 		WebElement nameEl = browser.findElement(nameBy);
 		nameEl.sendKeys(title);
-		By summaryBy = By.cssSelector(".o_sel_pf_edit_assignment_summary textarea");
-		WebElement summaryEl = browser.findElement(summaryBy);
-		summaryEl.sendKeys(summary);
+		OOGraphene.tinymce(summary, ".o_sel_pf_edit_assignment_summary", browser);
+		OOGraphene.tinymce(content, ".o_sel_pf_edit_assignment_content", browser);
 		
 		//save
 		By submitBy = By.cssSelector(".o_sel_pf_edit_assignment_form button.btn-primary");
diff --git a/src/test/java/org/olat/selenium/page/portfolio/BindersPage.java b/src/test/java/org/olat/selenium/page/portfolio/BindersPage.java
index 92bfadc82e3..089ea3b867a 100644
--- a/src/test/java/org/olat/selenium/page/portfolio/BindersPage.java
+++ b/src/test/java/org/olat/selenium/page/portfolio/BindersPage.java
@@ -53,9 +53,7 @@ public class BindersPage {
 		By nameBy = By.cssSelector(".o_sel_pf_edit_binder_title input[type='text']");
 		WebElement nameEl = browser.findElement(nameBy);
 		nameEl.sendKeys(title);
-		By summaryBy = By.cssSelector(".o_sel_pf_edit_binder_summary textarea");
-		WebElement summaryEl = browser.findElement(summaryBy);
-		summaryEl.sendKeys(summary);
+		OOGraphene.tinymce(summary, ".o_sel_pf_edit_binder_summary", browser);
 		
 		//save
 		By submitBy = By.cssSelector(".o_sel_pf_edit_binder_form button.btn-primary");
-- 
GitLab