From 2ce7f93e7f5c9db9fbffe58d1ab98cc46c4e1122 Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Tue, 3 Sep 2019 10:14:48 +0200
Subject: [PATCH] OO-4150: refinement of panel for multi-lectures blocks per
 participant

---
 .../olat/modules/lecture/LectureService.java  |  2 +
 .../lecture/manager/AbsenceNoticeDAO.java     |  3 +-
 .../lecture/manager/LectureServiceImpl.java   |  3 +-
 .../ui/SingleParticipantRollCallRow.java      | 20 +++-
 .../SingleParticipantRollCallsController.java | 96 ++++++++++++++-----
 .../SingleParticipantRollCallsDataModel.java  | 23 ++++-
 .../lecture/ui/TeacherRollCallController.java |  2 +-
 7 files changed, 120 insertions(+), 29 deletions(-)

diff --git a/src/main/java/org/olat/modules/lecture/LectureService.java b/src/main/java/org/olat/modules/lecture/LectureService.java
index 214eeea05d3..249e79a6102 100644
--- a/src/main/java/org/olat/modules/lecture/LectureService.java
+++ b/src/main/java/org/olat/modules/lecture/LectureService.java
@@ -340,6 +340,8 @@ public interface LectureService {
 	 */
 	public AbsenceNotice getAbsenceNotice(AbsenceNoticeRef notice);
 	
+	public AbsenceNotice getAbsenceNotice(IdentityRef identity, LectureBlock lectureBlock);
+	
 	public List<AbsenceNotice> getAbsenceNoticeRelatedTo(LectureBlock block);
 
 	public List<AbsenceNoticeInfos> searchAbsenceNotices(AbsenceNoticeSearchParameters searchParams);
diff --git a/src/main/java/org/olat/modules/lecture/manager/AbsenceNoticeDAO.java b/src/main/java/org/olat/modules/lecture/manager/AbsenceNoticeDAO.java
index 14fb26c8632..6a478f8d803 100644
--- a/src/main/java/org/olat/modules/lecture/manager/AbsenceNoticeDAO.java
+++ b/src/main/java/org/olat/modules/lecture/manager/AbsenceNoticeDAO.java
@@ -28,6 +28,7 @@ import javax.persistence.TemporalType;
 import javax.persistence.TypedQuery;
 
 import org.olat.basesecurity.GroupRoles;
+import org.olat.basesecurity.IdentityRef;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.persistence.QueryBuilder;
 import org.olat.core.id.Identity;
@@ -331,7 +332,7 @@ public class AbsenceNoticeDAO {
 	 * @param lectureBlock The lecture block (mandatory)
 	 * @return
 	 */
-	public List<AbsenceNotice> getAbsenceNotices(Identity calleeIdentity, LectureBlock lectureBlock) {
+	public List<AbsenceNotice> getAbsenceNotices(IdentityRef calleeIdentity, LectureBlock lectureBlock) {
 		QueryBuilder sb = new QueryBuilder(1024);
 		sb.append("select notice from absencenotice as notice")
 		  .append(" inner join fetch notice.identity as aIdent")
diff --git a/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java b/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java
index d78539057d3..4fca83cad13 100644
--- a/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java
+++ b/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java
@@ -1185,7 +1185,8 @@ public class LectureServiceImpl implements LectureService, UserDataDeletable, De
 		auditLog(LectureBlockAuditLog.Action.saveLectureBlock, before, after, null, lectureBlock, null, lectureBlock.getEntry(), null, teacher);
 	}
 
-	private AbsenceNotice getAbsenceNotice(Identity identity, LectureBlock lectureBlock) {
+	@Override
+	public AbsenceNotice getAbsenceNotice(IdentityRef identity, LectureBlock lectureBlock) {
 		List<AbsenceNotice> notices = absenceNoticeDao.getAbsenceNotices(identity, lectureBlock);
 		AbsenceNotice preferedNotice;
 		if(notices.isEmpty()) {
diff --git a/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallRow.java b/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallRow.java
index 9d7317eaeb5..85da287aa15 100644
--- a/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallRow.java
+++ b/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallRow.java
@@ -19,10 +19,13 @@
  */
 package org.olat.modules.lecture.ui;
 
+import java.util.List;
+
 import org.olat.core.gui.components.form.flexible.elements.FormLink;
 import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+import org.olat.core.id.Identity;
 import org.olat.modules.lecture.AbsenceNotice;
 import org.olat.modules.lecture.LectureBlock;
 import org.olat.modules.lecture.LectureBlockRollCall;
@@ -41,8 +44,10 @@ public class SingleParticipantRollCallRow implements RollCallRow, RollCallItem {
 	private final LectureBlock lectureBlock;
 	private final AbsenceNotice absenceNotice;
 	private LectureBlockRollCall rollCall;
+	private List<Identity> teachers;
 
 	private FormLink allLink;
+	private FormLink noticeLink;
 	private FormLink reasonLink;
 	private TextElement commentEl;
 	private MultipleSelectionElement[] checks;
@@ -50,10 +55,11 @@ public class SingleParticipantRollCallRow implements RollCallRow, RollCallItem {
 	private FormLayoutContainer authorizedAbsenceCont;
 	private LectureBlockRollCallStatusItem rollCallStatusEl;
 	
-	public SingleParticipantRollCallRow(LectureBlock lectureBlock, AbsenceNotice absenceNotice, int numOfLectures) {
+	public SingleParticipantRollCallRow(LectureBlock lectureBlock, AbsenceNotice absenceNotice, int numOfLectures, List<Identity> teachers) {
 		this.lectureBlock = lectureBlock;
 		this.absenceNotice = absenceNotice;
 		this.numOfLectures = numOfLectures;
+		this.teachers = teachers;
 	}
 	
 	public int getNumOfLectures() {
@@ -77,6 +83,10 @@ public class SingleParticipantRollCallRow implements RollCallRow, RollCallItem {
 		return absenceNotice;
 	}
 
+	public List<Identity> getTeachers() {
+		return teachers;
+	}
+
 	@Override
 	public LectureBlockRollCall getRollCall() {
 		return rollCall;
@@ -147,6 +157,14 @@ public class SingleParticipantRollCallRow implements RollCallRow, RollCallItem {
 		this.reasonLink = reasonLink;
 	}
 
+	public FormLink getNoticeLink() {
+		return noticeLink;
+	}
+
+	public void setNoticeLink(FormLink noticeLink) {
+		this.noticeLink = noticeLink;
+	}
+
 	@Override
 	public MultipleSelectionElement getAuthorizedAbsence() {
 		return authorizedAbsence;
diff --git a/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallsController.java b/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallsController.java
index 77032d0bf75..dc23aeede9d 100644
--- a/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallsController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallsController.java
@@ -28,6 +28,7 @@ import java.util.Map;
 
 import org.olat.admin.user.UserShortDescription;
 import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.EscapeMode;
 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.FlexiTableElement;
@@ -40,6 +41,7 @@ import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer;
 import org.olat.core.gui.components.link.Link;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
@@ -57,11 +59,15 @@ import org.olat.modules.lecture.LectureBlockStatus;
 import org.olat.modules.lecture.LectureModule;
 import org.olat.modules.lecture.LectureService;
 import org.olat.modules.lecture.RollCallSecurityCallback;
+import org.olat.modules.lecture.model.LectureBlockWithTeachers;
+import org.olat.modules.lecture.model.LecturesBlockSearchParameters;
 import org.olat.modules.lecture.model.RollCallSecurityCallbackImpl;
 import org.olat.modules.lecture.ui.SingleParticipantRollCallsDataModel.RollCallsCols;
+import org.olat.modules.lecture.ui.coach.AbsenceNoticeDetailsCalloutController;
 import org.olat.modules.lecture.ui.component.LectureBlockRollCallStatusItem;
 import org.olat.modules.lecture.ui.component.LectureBlockTimesCellRenderer;
 import org.olat.user.DisplayPortraitController;
+import org.olat.user.UserManager;
 import org.springframework.beans.factory.annotation.Autowired;
 
 /**
@@ -91,8 +97,12 @@ public class SingleParticipantRollCallsController extends FormBasicController {
 	private final Map<LectureBlock,RollCallSecurityCallback> secCallbacks;
 	
 	private ReasonController reasonCtrl;
-	private CloseableCalloutWindowController reasonCalloutCtrl; 
+	private CloseableCalloutWindowController noticeCalloutCtrl;
+	private CloseableCalloutWindowController reasonCalloutCtrl;
+	private AbsenceNoticeDetailsCalloutController noticeDetailsCtrl;
 	
+	@Autowired
+	private UserManager userManager;
 	@Autowired
 	private LectureModule lectureModule;
 	@Autowired
@@ -162,8 +172,9 @@ public class SingleParticipantRollCallsController extends FormBasicController {
 		FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
 		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RollCallsCols.entry));
 		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RollCallsCols.externalRef));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RollCallsCols.lecturesBlock));
 		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RollCallsCols.times, new LectureBlockTimesCellRenderer(getLocale())));
-		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RollCallsCols.teacher));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RollCallsCols.teacher, new TextFlexiCellRenderer(EscapeMode.antisamy)));
 		
 		boolean canViewAuthorizedAbsences = secCallbacks.values()
 				.stream().anyMatch(RollCallSecurityCallback::canViewAuthorizedAbsences);
@@ -192,7 +203,7 @@ public class SingleParticipantRollCallsController extends FormBasicController {
 		
 		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RollCallsCols.comment));
 		
-		tableModel = new SingleParticipantRollCallsDataModel(columnsModel);
+		tableModel = new SingleParticipantRollCallsDataModel(columnsModel, userManager);
 		
 		tableEl = uifactory.addTableElement(getWindowControl(), "table", tableModel, 24, false, getTranslator(), formLayout);
 		
@@ -201,6 +212,11 @@ public class SingleParticipantRollCallsController extends FormBasicController {
 	}
 	
 	private void loadModel() {
+		LecturesBlockSearchParameters searchParams = new LecturesBlockSearchParameters();
+		searchParams.setLectureBlocks(lectureBlocks);
+		List<LectureBlockWithTeachers> lectureBlocksWithTeachers = lectureService.getLectureBlocksWithTeachers(searchParams);
+		
+		
 		List<SingleParticipantRollCallRow> rows = new ArrayList<>(lectureBlocks.size());
 		for(LectureBlock lectureBlock:lectureBlocks) {
 			LectureBlockRollCall lectureCall = null;
@@ -209,18 +225,32 @@ public class SingleParticipantRollCallsController extends FormBasicController {
 					lectureCall = call;
 				}
 			}
-			AbsenceNotice notice = null;//TODO absences notice
+			
+			List<Identity> teachers = null;
+			for(LectureBlockWithTeachers lectureBlockWithTeachers:lectureBlocksWithTeachers) {
+				if(lectureBlockWithTeachers.getLectureBlock().equals(lectureBlock)) {
+					teachers = lectureBlockWithTeachers.getTeachers();
+				}
+			}
+
+			AbsenceNotice notice = null;
+			if(lectureCall != null) {
+				notice = lectureCall.getAbsenceNotice();
+			} else {
+				notice = lectureService.getAbsenceNotice(calledIdentity, lectureBlock);
+			}
 			RollCallSecurityCallback secCallback = secCallbacks.get(lectureBlock);
-			rows.add(forgeRow(lectureBlock, lectureCall, notice, secCallback));
+			rows.add(forgeRow(lectureBlock, lectureCall, notice, teachers, secCallback));
 		}
 		
 		tableModel.setObjects(rows);
 		tableEl.reset(true, true, true);
 	}
 	
-	private SingleParticipantRollCallRow forgeRow(LectureBlock lectureBlock, LectureBlockRollCall rollCall, AbsenceNotice notice, RollCallSecurityCallback secCallback) {
+	private SingleParticipantRollCallRow forgeRow(LectureBlock lectureBlock, LectureBlockRollCall rollCall,
+			AbsenceNotice notice, List<Identity> teachers, RollCallSecurityCallback secCallback) {
 		int numOfLectures = numOfLectures(lectureBlock);
-		SingleParticipantRollCallRow row = new SingleParticipantRollCallRow(lectureBlock, notice, numOfLectures);
+		SingleParticipantRollCallRow row = new SingleParticipantRollCallRow(lectureBlock, notice, numOfLectures, teachers);
 		
 		int numOfChecks = lectureBlock.isCompulsory() ? numOfLectures : 0;
 		MultipleSelectionElement[] checks = new MultipleSelectionElement[numOfChecks];
@@ -231,17 +261,16 @@ public class SingleParticipantRollCallsController extends FormBasicController {
 			MultipleSelectionElement check = uifactory.addCheckboxesHorizontal(checkId, null, flc, onKeys, onValues);
 			check.setDomReplacementWrapperRequired(false);
 			check.addActionListener(FormEvent.ONCHANGE);
-			check.setEnabled(secCallback.canEditAbsences());
+			check.setEnabled(secCallback.canEditAbsences() && notice == null);
 			check.setUserObject(row);
 			check.setAjaxOnly(true);
-			if(absences.contains(i)) {
+			if(absences.contains(i) || notice != null) {
 				check.select(onKeys[0], true);
 			}
 			checks[i] = check;
 			flc.add(check);
 		}
 		row.setChecks(checks);
-		
 
 		LectureBlockRollCallStatusItem statusEl = new LectureBlockRollCallStatusItem("status_".concat(Integer.toString(++counter)),
 				row, authorizedAbsenceEnabled, absenceDefaultAuthorized, getTranslator());
@@ -259,7 +288,7 @@ public class SingleParticipantRollCallsController extends FormBasicController {
 			authorizedAbsencedEl.addActionListener(FormEvent.ONCHANGE);
 			authorizedAbsencedEl.setUserObject(row);
 			authorizedAbsencedEl.setAjaxOnly(true);
-			authorizedAbsencedEl.setEnabled(secCallback.canEdit() && secCallback.canEditAuthorizedAbsences());
+			authorizedAbsencedEl.setEnabled(secCallback.canEdit() && secCallback.canEditAuthorizedAbsences() && notice == null);
 			
 			boolean hasAuthorization = rollCall != null && rollCall.getAbsenceAuthorized() != null
 					&& rollCall.getAbsenceAuthorized().booleanValue();
@@ -268,21 +297,31 @@ public class SingleParticipantRollCallsController extends FormBasicController {
 			}
 			row.setAuthorizedAbsence(authorizedAbsencedEl);
 			flc.add(authorizedAbsencedEl);
-
-			String reasonId = "abs_reason_".concat(Integer.toString(++counter));
-			FormLink reasonLink = uifactory.addFormLink(reasonId, "", null, absenceCont, Link.BUTTON_XSMALL | Link.NONTRANSLATED);
-			reasonLink.setTitle(translate("reason"));
-			reasonLink.setDomReplacementWrapperRequired(false);
-			reasonLink.setIconLeftCSS("o_icon o_icon_notes");
-			reasonLink.setVisible(hasAuthorization);
-			reasonLink.setUserObject(row);
-			row.setReasonLink(reasonLink);
+			
+			if(notice != null) {
+				String noticeId = "notice_".concat(Integer.toString(++counter));
+				FormLink noticeLink = uifactory.addFormLink(noticeId, "", null, absenceCont, Link.LINK | Link.NONTRANSLATED);
+				noticeLink.setTitle(translate("reason"));
+				noticeLink.setDomReplacementWrapperRequired(false);
+				noticeLink.setIconLeftCSS("o_icon o_icon_info");
+				noticeLink.setUserObject(row);
+				row.setNoticeLink(noticeLink);
+			} else {
+				String reasonId = "abs_reason_".concat(Integer.toString(++counter));
+				FormLink reasonLink = uifactory.addFormLink(reasonId, "", null, absenceCont, Link.BUTTON_XSMALL | Link.NONTRANSLATED);
+				reasonLink.setTitle(translate("reason"));
+				reasonLink.setDomReplacementWrapperRequired(false);
+				reasonLink.setIconLeftCSS("o_icon o_icon_notes");
+				reasonLink.setVisible(hasAuthorization);
+				reasonLink.setUserObject(row);
+				row.setReasonLink(reasonLink);
+			}
 			
 			row.setAuthorizedAbsenceCont(absenceCont);
 			absenceCont.contextPut("row", row);
 		}
 		
-		if(secCallback.canEditAbsences()) {
+		if(secCallback.canEditAbsences() && notice == null) {
 			FormLink allLink = uifactory.addFormLink("all_".concat(Integer.toString(++counter)), "all", null, flc, Link.LINK);
 			allLink.setTitle("all.desc");
 			allLink.setDomReplacementWrapperRequired(false);
@@ -327,7 +366,8 @@ public class SingleParticipantRollCallsController extends FormBasicController {
 				//??? stop?
 			} else if(!absenceDefaultAuthorized) {
 				String reason = row.getRollCall().getAbsenceReason();
-				if(row.getAuthorizedAbsence() != null && row.getAuthorizedAbsence().isAtLeastSelected(1) && !StringHelper.containsNonWhitespace(reason)) {
+				if(row.getAbsenceNotice() == null && row.getAuthorizedAbsence() != null
+						&& row.getAuthorizedAbsence().isAtLeastSelected(1) && !StringHelper.containsNonWhitespace(reason)) {
 					row.getAuthorizedAbsence().setErrorKey("error.reason.mandatory", null);
 					allOk &= false;
 				}
@@ -380,6 +420,8 @@ public class SingleParticipantRollCallsController extends FormBasicController {
 					doCalloutReasonAbsence(ureq, link.getFormDispatchId(), row);
 				} else if(cmd.startsWith("all_")) {
 					doCheckAllRow((SingleParticipantRollCallRow)link.getUserObject());
+				}else if(cmd.startsWith("notice_")) {
+					doCalloutAbsenceNotice(ureq, link.getFormDispatchId(), (SingleParticipantRollCallRow)link.getUserObject());
 				}
 			}
 		}
@@ -397,6 +439,16 @@ public class SingleParticipantRollCallsController extends FormBasicController {
 		fireEvent(ureq, Event.CANCELLED_EVENT);
 	}
 	
+	private void doCalloutAbsenceNotice(UserRequest ureq, String elementId, SingleParticipantRollCallRow row) {
+		noticeDetailsCtrl = new AbsenceNoticeDetailsCalloutController(ureq, getWindowControl(), row.getAbsenceNotice());
+		listenTo(noticeDetailsCtrl);
+
+		noticeCalloutCtrl = new CloseableCalloutWindowController(ureq, getWindowControl(),
+				noticeDetailsCtrl.getInitialComponent(), elementId, "", true, "");
+		listenTo(noticeCalloutCtrl);
+		noticeCalloutCtrl.activate();
+	}
+	
 	private void doReason(SingleParticipantRollCallRow row, String reason, AbsenceCategory category) {
 		LectureBlockRollCall rollCall = row.getRollCall();
 		String before = lectureService.toAuditXml(rollCall);
diff --git a/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallsDataModel.java b/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallsDataModel.java
index 9570d3edd81..d0128285f17 100644
--- a/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallsDataModel.java
+++ b/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallsDataModel.java
@@ -22,6 +22,8 @@ package org.olat.modules.lecture.ui;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataModel;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiSortableColumnDef;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
+import org.olat.core.id.Identity;
+import org.olat.user.UserManager;
 
 /**
  * 
@@ -30,9 +32,12 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable
  *
  */
 public class SingleParticipantRollCallsDataModel extends DefaultFlexiTableDataModel<SingleParticipantRollCallRow> {
+
+	private final UserManager userManager;
 	
-	public SingleParticipantRollCallsDataModel(FlexiTableColumnModel columnModel) {
+	public SingleParticipantRollCallsDataModel(FlexiTableColumnModel columnModel, UserManager userManager) {
 		super(columnModel);
+		this.userManager = userManager;
 	}
 
 	@Override
@@ -42,8 +47,9 @@ public class SingleParticipantRollCallsDataModel extends DefaultFlexiTableDataMo
 			switch(RollCallsCols.values()[col]) {
 				case entry: return call.getEntryDisplayname();
 				case externalRef: return call.getEntryExternalRef();
+				case lecturesBlock: return call.getLectureBlock().getTitle();
 				case times: return call.getLectureBlock();
-				case teacher: return "TEACHER";
+				case teacher: return getTeachers(call);
 				case status: return call.getRollCallStatusEl(); 
 				case authorizedAbsence: return call.getAuthorizedAbsenceCont();
 				case comment: return call.getCommentEl();
@@ -54,15 +60,26 @@ public class SingleParticipantRollCallsDataModel extends DefaultFlexiTableDataMo
 		int propPos = col - TeacherRollCallController.CHECKBOX_OFFSET;
 		return call.getCheck(propPos);
 	}
+	
+	private String getTeachers(SingleParticipantRollCallRow row) {
+		StringBuilder sb = new StringBuilder(1024);
+		for(Identity teacher:row.getTeachers()) {
+			sb.append("<i class='o_icon o_icon_user'> </i> ")
+			  .append(userManager.getUserDisplayName(teacher))
+			  .append(" ");	
+		}
+		return sb.toString();
+	}
 
 	@Override
 	public DefaultFlexiTableDataModel<SingleParticipantRollCallRow> createCopyWithEmptyList() {
-		return new SingleParticipantRollCallsDataModel(getTableColumnModel());
+		return new SingleParticipantRollCallsDataModel(getTableColumnModel(), userManager);
 	}
 
 	public enum RollCallsCols implements FlexiSortableColumnDef {
 		entry("table.header.entry"),
 		externalRef("table.header.external.ref"),
+		lecturesBlock("table.header.lecture.block"),
 		times("table.header.times"),
 		teacher("table.header.teachers"),
 		status("table.header.status"),
diff --git a/src/main/java/org/olat/modules/lecture/ui/TeacherRollCallController.java b/src/main/java/org/olat/modules/lecture/ui/TeacherRollCallController.java
index 258aa82ac10..d59c13e26a3 100644
--- a/src/main/java/org/olat/modules/lecture/ui/TeacherRollCallController.java
+++ b/src/main/java/org/olat/modules/lecture/ui/TeacherRollCallController.java
@@ -393,7 +393,7 @@ public class TeacherRollCallController extends FormBasicController {
 			absenceCont.contextPut("row", row);
 		}
 		
-		if(secCallback.canEditAbsences()) {
+		if(secCallback.canEditAbsences() && notice == null) {
 			FormLink allLink = uifactory.addFormLink("all_".concat(Integer.toString(++counter)), "all", null, flc, Link.LINK);
 			allLink.setTitle("all.desc");
 			allLink.setDomReplacementWrapperRequired(false);
-- 
GitLab