diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentTestSessionDetailsNumberRenderer.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentTestSessionDetailsNumberRenderer.java index 78f0739c97296c8c0cf2d660eded80d8010d38db..3350f1a17c0824e45ffcee35dec37922a30b6262 100644 --- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentTestSessionDetailsNumberRenderer.java +++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentTestSessionDetailsNumberRenderer.java @@ -1,3 +1,22 @@ +/** + * <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.ims.qti21.ui.components; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer; diff --git a/src/main/java/org/olat/modules/lecture/LectureBlock.java b/src/main/java/org/olat/modules/lecture/LectureBlock.java index 0ccd30e1d52f58ed825fb1ba837b1029d59ae608..710bca0c56677a4004e48a0a6eed5a270cfd5706 100644 --- a/src/main/java/org/olat/modules/lecture/LectureBlock.java +++ b/src/main/java/org/olat/modules/lecture/LectureBlock.java @@ -77,6 +77,12 @@ public interface LectureBlock extends LectureBlockRef, ModifiedInfo, CreateInfo, public int getEffectiveLecturesNumber(); public void setEffectiveLecturesNumber(int effectiveLecturesNumber); + + /** + * @return The calculated number of lectures dependent of planned and + * effective lectures and the status of the block. + */ + public int getCalculatedLecturesNumber(); public Date getStartDate(); diff --git a/src/main/java/org/olat/modules/lecture/LectureService.java b/src/main/java/org/olat/modules/lecture/LectureService.java index 93712fef9d8692b3ef745d0dd35756ddb1d7e54d..7da377a61231b9ceb4eac0aaf552dc48d3fddf70 100644 --- a/src/main/java/org/olat/modules/lecture/LectureService.java +++ b/src/main/java/org/olat/modules/lecture/LectureService.java @@ -324,7 +324,7 @@ public interface LectureService { /** * Delete the absence notice and remove the absences from the roll calls. * - * @param absenceNotice Absence nnotice to delete + * @param absenceNotice Absence notice to delete */ public void deleteAbsenceNotice(AbsenceNotice absenceNotice, Identity actingIdentity); diff --git a/src/main/java/org/olat/modules/lecture/manager/LectureBlockRollCallDAO.java b/src/main/java/org/olat/modules/lecture/manager/LectureBlockRollCallDAO.java index 38c3f1241145dce5cb66912fd54313ecdae8d6f6..f3f9d27f6089f4865b531f08e1f8bcb790d3331e 100644 --- a/src/main/java/org/olat/modules/lecture/manager/LectureBlockRollCallDAO.java +++ b/src/main/java/org/olat/modules/lecture/manager/LectureBlockRollCallDAO.java @@ -120,11 +120,8 @@ public class LectureBlockRollCallDAO { call.setLecturesAbsentList(currentAbsentList); call.setLecturesAbsentNumber(currentAbsentList.size()); - int numOfLectures = lectureBlock.getEffectiveLecturesNumber(); - if(numOfLectures <= 0 && lectureBlock.getStatus() != LectureBlockStatus.cancelled) { - numOfLectures = lectureBlock.getPlannedLecturesNumber(); - } - + int numOfLectures = lectureBlock.getCalculatedLecturesNumber(); + List<Integer> attendedList = new ArrayList<>(); for(int i=0; i<numOfLectures; i++) { if(!currentAbsentList.contains(i)) { @@ -152,10 +149,7 @@ public class LectureBlockRollCallDAO { call.setLecturesAbsentList(currentAbsentList); call.setLecturesAbsentNumber(currentAbsentList.size()); - int numOfLectures = lectureBlock.getEffectiveLecturesNumber(); - if(numOfLectures <= 0 && lectureBlock.getStatus() != LectureBlockStatus.cancelled) { - numOfLectures = lectureBlock.getPlannedLecturesNumber(); - } + int numOfLectures = lectureBlock.getCalculatedLecturesNumber(); List<Integer> attendedList = new ArrayList<>(); for(int i=0; i<numOfLectures; i++) { @@ -178,7 +172,7 @@ public class LectureBlockRollCallDAO { List<Integer> currentAbsentList = call.getLecturesAbsentList(); List<Integer> currentAttendedList = call.getLecturesAttendedList(); - if((currentAbsentList != null && currentAbsentList.size() > 0) || (currentAttendedList != null && currentAttendedList.size() > 0)) { + if((currentAbsentList != null && !currentAbsentList.isEmpty()) || (currentAttendedList != null && !currentAttendedList.isEmpty())) { String before = auditLogDao.toXml(rollCall); int currentLectures = currentAbsentList.size() + currentAttendedList.size(); @@ -877,7 +871,7 @@ public class LectureBlockRollCallDAO { String qName = "p_" + ++count; UserPropertyHandler handler = userManager.getUserPropertiesConfig().getPropertyHandler(propName); - if(handler == null) {// fallback if the haandler is disabled + if(handler == null) {// fallback if the handler is disabled for(UserPropertyHandler userPropertyHandler:userPropertyHandlers) { if(propName.equals(userPropertyHandler.getName())) { handler = userPropertyHandler; 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 2de251907aee2cf57a50e5f65e7525a4e5dd66ca..500f3219262902b4c7abafc20a659dc321f579be 100644 --- a/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java +++ b/src/main/java/org/olat/modules/lecture/manager/LectureServiceImpl.java @@ -268,11 +268,8 @@ public class LectureServiceImpl implements LectureService, UserDataDeletable, De lectureBlock.setRollCallStatus(LectureRollCallStatus.closed); LectureBlockImpl block = (LectureBlockImpl)lectureBlockDao.update(lectureBlock); - int numOfLectures = block.getEffectiveLecturesNumber(); - if(numOfLectures <= 0 && block.getStatus() != LectureBlockStatus.cancelled) { - numOfLectures = block.getPlannedLecturesNumber(); - } - + int numOfLectures = block.getCalculatedLecturesNumber(); + List<LectureBlockRollCall> rollCallList = lectureBlockRollCallDao.getRollCalls(lectureBlock); for(LectureBlockRollCall rollCall:rollCallList) { lectureBlockRollCallDao.adaptLecture(block, rollCall, numOfLectures, author); @@ -1140,10 +1137,7 @@ public class LectureServiceImpl implements LectureService, UserDataDeletable, De Map<Identity,LectureBlockRollCall> identityToRollCallMap = rollCalls.stream() .collect(Collectors.toMap(LectureBlockRollCall::getIdentity, call -> call, (u, v) -> u)); - int numOfLectures = lectureBlock.getEffectiveLecturesNumber(); - if(numOfLectures <= 0 && lectureBlock.getStatus() != LectureBlockStatus.cancelled) { - numOfLectures = lectureBlock.getPlannedLecturesNumber(); - } + int numOfLectures = lectureBlock.getCalculatedLecturesNumber(); for(Identity participant:participants) { LectureBlockRollCall rollCall = identityToRollCallMap.get(participant); @@ -1211,10 +1205,7 @@ public class LectureServiceImpl implements LectureService, UserDataDeletable, De List<LectureBlockRollCall> rollCallList = lectureBlockRollCallDao.getRollCalls(lectureBlock); for(LectureBlockRollCall rollCall:rollCallList) { - int numOfLectures = lectureBlock.getEffectiveLecturesNumber(); - if(numOfLectures <= 0 && lectureBlock.getStatus() != LectureBlockStatus.cancelled) { - numOfLectures = lectureBlock.getPlannedLecturesNumber(); - } + int numOfLectures = lectureBlock.getCalculatedLecturesNumber(); lectureBlockRollCallDao.adaptLecture(lectureBlock, rollCall, numOfLectures, null); } } @@ -1225,10 +1216,7 @@ public class LectureServiceImpl implements LectureService, UserDataDeletable, De for(LectureBlock lectureBlock:lectureBlocks) { List<LectureBlockRollCall> rollCallList = lectureBlockRollCallDao.getRollCalls(lectureBlock); for(LectureBlockRollCall rollCall:rollCallList) { - int numOfLectures = lectureBlock.getEffectiveLecturesNumber(); - if(numOfLectures <= 0 && lectureBlock.getStatus() != LectureBlockStatus.cancelled) { - numOfLectures = lectureBlock.getPlannedLecturesNumber(); - } + int numOfLectures = lectureBlock.getCalculatedLecturesNumber(); lectureBlockRollCallDao.adaptLecture(lectureBlock, rollCall, numOfLectures, author); } dbInstance.commitAndCloseSession(); diff --git a/src/main/java/org/olat/modules/lecture/model/LectureBlockAndRollCall.java b/src/main/java/org/olat/modules/lecture/model/LectureBlockAndRollCall.java index a1fa9d47724ddd68251fe16f5178670593675a16..4354b1fd92fad7809ab1ba06cb20163950149dc4 100644 --- a/src/main/java/org/olat/modules/lecture/model/LectureBlockAndRollCall.java +++ b/src/main/java/org/olat/modules/lecture/model/LectureBlockAndRollCall.java @@ -88,11 +88,7 @@ public class LectureBlockAndRollCall { if(absenceNotice != null) { lecturesAttendedNumber = 0; - int numOfLectures = lectureBlock.getEffectiveLecturesNumber(); - if(numOfLectures <= 0) { - numOfLectures = lectureBlock.getPlannedLecturesNumber(); - } - lecturesAbsentNumber = numOfLectures; + lecturesAbsentNumber = lectureBlock.getCalculatedLecturesNumber(); lecturesAuthorizedAbsent = absenceNotice.getAbsenceAuthorized(); } else { lecturesAttendedNumber = rollCall.getLecturesAttendedNumber(); diff --git a/src/main/java/org/olat/modules/lecture/model/LectureBlockImpl.java b/src/main/java/org/olat/modules/lecture/model/LectureBlockImpl.java index a1e8aacbe86cfbcb6187123865efca80cf151e3f..40a9bf6ed7b3f9705cbb4580b5c5802e1fbe7820 100644 --- a/src/main/java/org/olat/modules/lecture/model/LectureBlockImpl.java +++ b/src/main/java/org/olat/modules/lecture/model/LectureBlockImpl.java @@ -36,6 +36,7 @@ import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; +import javax.persistence.Transient; import org.olat.basesecurity.Group; import org.olat.basesecurity.model.GroupImpl; @@ -274,6 +275,16 @@ public class LectureBlockImpl implements Persistable, LectureBlock { public void setEffectiveLecturesNumber(int effectiveLecturesNumber) { this.effectiveLecturesNumber = effectiveLecturesNumber; } + + @Transient + @Override + public int getCalculatedLecturesNumber() { + int numOfLectures = getEffectiveLecturesNumber(); + if(numOfLectures <= 0 && getStatus() != LectureBlockStatus.cancelled) { + numOfLectures = getPlannedLecturesNumber(); + } + return numOfLectures; + } @Override public Date getStartDate() { 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 dc23aeede9d7ef49d6caccbccf12525ef8a6ba3a..4a61fa1bfe83ad50036202c53850e5aa3f362128 100644 --- a/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallsController.java +++ b/src/main/java/org/olat/modules/lecture/ui/SingleParticipantRollCallsController.java @@ -55,7 +55,6 @@ import org.olat.modules.lecture.AbsenceNotice; import org.olat.modules.lecture.LectureBlock; import org.olat.modules.lecture.LectureBlockAuditLog; import org.olat.modules.lecture.LectureBlockRollCall; -import org.olat.modules.lecture.LectureBlockStatus; import org.olat.modules.lecture.LectureModule; import org.olat.modules.lecture.LectureService; import org.olat.modules.lecture.RollCallSecurityCallback; @@ -118,7 +117,7 @@ public class SingleParticipantRollCallsController extends FormBasicController { hasCompulsory = lectureBlocks.stream() .anyMatch(LectureBlock::isCompulsory); maxNumOfLectures = lectureBlocks.stream() - .mapToInt(SingleParticipantRollCallsController::numOfLectures) + .mapToInt(LectureBlock::getCalculatedLecturesNumber) .max().orElse(0); authorizedAbsenceEnabled = lectureModule.isAuthorizedAbsenceEnabled(); absenceDefaultAuthorized = lectureModule.isAbsenceDefaultAuthorized(); @@ -138,14 +137,6 @@ public class SingleParticipantRollCallsController extends FormBasicController { return secCallbackMap; } - private static int numOfLectures(LectureBlock lectureBlock) { - int numOfLectures = lectureBlock.getEffectiveLecturesNumber(); - if(numOfLectures <= 0 && lectureBlock.getStatus() != LectureBlockStatus.cancelled) { - numOfLectures = lectureBlock.getPlannedLecturesNumber(); - } - return numOfLectures; - } - @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { // identity screen and title @@ -249,7 +240,7 @@ public class SingleParticipantRollCallsController extends FormBasicController { private SingleParticipantRollCallRow forgeRow(LectureBlock lectureBlock, LectureBlockRollCall rollCall, AbsenceNotice notice, List<Identity> teachers, RollCallSecurityCallback secCallback) { - int numOfLectures = numOfLectures(lectureBlock); + int numOfLectures = lectureBlock.getCalculatedLecturesNumber(); SingleParticipantRollCallRow row = new SingleParticipantRollCallRow(lectureBlock, notice, numOfLectures, teachers); int numOfChecks = lectureBlock.isCompulsory() ? numOfLectures : 0; @@ -385,7 +376,7 @@ public class SingleParticipantRollCallsController extends FormBasicController { } reasonCalloutCtrl.deactivate(); cleanUp(); - } else if(reasonCalloutCtrl == source) { + } else if(reasonCalloutCtrl == source || noticeCalloutCtrl == null) { cleanUp(); } super.event(ureq, source, event); @@ -393,8 +384,12 @@ public class SingleParticipantRollCallsController extends FormBasicController { private void cleanUp() { removeAsListenerAndDispose(reasonCalloutCtrl); + removeAsListenerAndDispose(noticeCalloutCtrl); + removeAsListenerAndDispose(noticeDetailsCtrl); removeAsListenerAndDispose(reasonCtrl); reasonCalloutCtrl = null; + noticeCalloutCtrl = null; + noticeDetailsCtrl = null; reasonCtrl = null; } 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 3e9feb4cd630b96435c73956dc67964c121afc5c..1c146072f4d94be913c0a65619e4e8191dfbd3e1 100644 --- a/src/main/java/org/olat/modules/lecture/ui/TeacherRollCallController.java +++ b/src/main/java/org/olat/modules/lecture/ui/TeacherRollCallController.java @@ -139,11 +139,8 @@ public class TeacherRollCallController extends FormBasicController { this.withBack = withBack; setTranslator(userManager.getPropertyHandlerTranslator(getTranslator())); - numOfLectures = lectureBlock.getEffectiveLecturesNumber(); - if(numOfLectures <= 0 && lectureBlock.getStatus() != LectureBlockStatus.cancelled) { - numOfLectures = lectureBlock.getPlannedLecturesNumber(); - } - + numOfLectures = lectureBlock.getCalculatedLecturesNumber(); + Roles roles = ureq.getUserSession().getRoles(); isAdministrativeUser = securityModule.isUserAllowedAdminProps(roles); userPropertyHandlers = userManager.getUserPropertyHandlersFor(USER_PROPS_ID, isAdministrativeUser); diff --git a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties index c5ed9039890b122a7423154ba434c5ec0adcdfe8..2c5c48da536f9a5d3f9f49bcf69129de73c8f1b1 100644 --- a/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/lecture/ui/_i18n/LocalStrings_de.properties @@ -488,6 +488,10 @@ table.header.times=Zeit table.header.tools=<i class\='o_icon o_icon_actions o_icon-lg'> </i> table.header.unauthorized.absence=Unentschuldigt table.header.username=Benutzername +table.lecture.explain=<strong>{4}</strong> {0} {1} - {2} f\u00FCr {3} Lektion +table.lectures.explain=<strong>{4}</strong> {0} {1} - {2} f\u00FCr {3} Lektionen +table.lecture.infos=1 Block +table.lectures.infos={0} Bl\u00F6cke table.legend.absent=Abwesend table.legend.attended=Anwesend table.legend.authorized=Entschuldigte Abwesenheit diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/AbsenceNoticesListController.java b/src/main/java/org/olat/modules/lecture/ui/coach/AbsenceNoticesListController.java index c0019d8d82cc555367ba3e09e6a2137c29e43a14..dcbc07603a2f9c3649e3b25b1586f380ae898c36 100644 --- a/src/main/java/org/olat/modules/lecture/ui/coach/AbsenceNoticesListController.java +++ b/src/main/java/org/olat/modules/lecture/ui/coach/AbsenceNoticesListController.java @@ -42,7 +42,6 @@ import org.olat.core.gui.components.form.flexible.elements.FormLink; import org.olat.core.gui.components.form.flexible.elements.SingleSelection; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormEvent; -import org.olat.core.gui.components.form.flexible.impl.elements.table.DateTimeFlexiCellRenderer; 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; @@ -75,6 +74,7 @@ import org.olat.modules.lecture.ui.LecturesSecurityCallback; import org.olat.modules.lecture.ui.coach.AbsenceNoticeHelper.AbsenceNoticeCSS; import org.olat.modules.lecture.ui.coach.AbsenceNoticesListTableModel.NoticeCols; import org.olat.modules.lecture.ui.component.DailyDateCellRenderer; +import org.olat.modules.lecture.ui.component.StartEndDateCellRenderer; import org.olat.modules.lecture.ui.event.OpenRepositoryEntryEvent; import org.olat.modules.lecture.ui.event.SelectLectureIdentityEvent; import org.olat.modules.lecture.ui.profile.IdentityProfileController; @@ -217,9 +217,9 @@ public class AbsenceNoticesListController extends FormBasicController { dailyDateRenderer = new DailyDateCellRenderer(currentDate, getLocale(), getTranslator()); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(NoticeCols.date, dailyDateRenderer)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(wholeDateDefault, NoticeCols.start, - new DateTimeFlexiCellRenderer(getLocale()))); + new StartEndDateCellRenderer(true, getLocale()))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(wholeDateDefault, NoticeCols.end, - new DateTimeFlexiCellRenderer(getLocale()))); + new StartEndDateCellRenderer(false, getLocale()))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, NoticeCols.reason)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(NoticeCols.details)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(NoticeCols.type)); @@ -538,6 +538,8 @@ public class AbsenceNoticesListController extends FormBasicController { } private void doOpenProfile(UserRequest ureq, AbsenceNoticeRow row) { + if(guardModalController(profileCtrl)) return; + profileCtrl = new IdentityProfileController(ureq, getWindowControl(), row.getAbsentIdentity(), secCallback, false); listenTo(profileCtrl); diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/AbsenceNoticesListTableModel.java b/src/main/java/org/olat/modules/lecture/ui/coach/AbsenceNoticesListTableModel.java index d05000b0c5a1897e57484c92ac3a66f536e1d927..6efcf239ae4f2501c4da6dc72f62225a81fcc8c1 100644 --- a/src/main/java/org/olat/modules/lecture/ui/coach/AbsenceNoticesListTableModel.java +++ b/src/main/java/org/olat/modules/lecture/ui/coach/AbsenceNoticesListTableModel.java @@ -33,7 +33,6 @@ import org.olat.core.id.User; import org.olat.course.assessment.ui.tool.AssessmentToolConstants; import org.olat.modules.lecture.AbsenceNotice; import org.olat.modules.lecture.LectureBlock; -import org.olat.modules.lecture.LectureBlockStatus; import org.olat.user.UserManager; import org.olat.user.propertyhandlers.UserPropertyHandler; @@ -78,7 +77,7 @@ implements SortableFlexiTableDataModel<AbsenceNoticeRow> { switch(NoticeCols.values()[col]) { case id: return row.getKey(); case username: return row.getIdentityName(); - case date: return row.getAbsenceNotice(); + case date: return row; case start: return row.getStartDate(); case end: return row.getEndDate(); case entry: return row.getEntriesLink(); @@ -119,11 +118,7 @@ implements SortableFlexiTableDataModel<AbsenceNoticeRow> { private int getNumOfLectures(AbsenceNoticeRow row) { int totalLectures = 0; for(LectureBlock lectureBlock:row.getLectureBlocks()) { - int numOfLectures = lectureBlock.getEffectiveLecturesNumber(); - if(numOfLectures <= 0 && lectureBlock.getStatus() != LectureBlockStatus.cancelled) { - numOfLectures = lectureBlock.getPlannedLecturesNumber(); - } - totalLectures += numOfLectures; + totalLectures += lectureBlock.getCalculatedLecturesNumber(); } return totalLectures; } diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/EditDatesLecturesEntriesController.java b/src/main/java/org/olat/modules/lecture/ui/coach/EditDatesLecturesEntriesController.java index e8bb4348cb3f98b0e40d8d22968543465d81ab37..96a94b1a6365286cfcd298b72f472be83e062d61 100644 --- a/src/main/java/org/olat/modules/lecture/ui/coach/EditDatesLecturesEntriesController.java +++ b/src/main/java/org/olat/modules/lecture/ui/coach/EditDatesLecturesEntriesController.java @@ -316,10 +316,11 @@ public class EditDatesLecturesEntriesController extends FormBasicController { private String getRepositoryEntryLabel(Map.Entry<RepositoryEntry, Long> entryOfMap) { RepositoryEntry entry = entryOfMap.getKey(); int numOfLectureBlocks = entryOfMap.getValue().intValue(); + String externalRef = StringHelper.containsNonWhitespace(entry.getExternalRef()) ? StringHelper.escapeHtml(entry.getExternalRef()) : ""; String[] args = new String[] { StringHelper.escapeHtml(entry.getDisplayname()), // 0 - StringHelper.escapeHtml(entry.getExternalRef()), // 1 + externalRef, // 1 Integer.toString(numOfLectureBlocks) }; @@ -377,9 +378,12 @@ public class EditDatesLecturesEntriesController extends FormBasicController { LectureBlock block = lectureBlock.getLectureBlock(); RepositoryEntry entry = block.getEntry(); + String entryExternalRef = StringHelper.containsNonWhitespace(entry.getExternalRef()) + ? StringHelper.escapeHtml(entry.getExternalRef()) : ""; + String[] args = new String[] { StringHelper.escapeHtml(entry.getDisplayname()), // 0 - StringHelper.escapeHtml(entry.getExternalRef()), // 1 + StringHelper.escapeHtml(entryExternalRef), // 1 formatter.formatDate(block.getStartDate()), // 2 formatter.formatTimeShort(block.getStartDate()), // 3 formatter.formatTimeShort(block.getEndDate()), // 4 diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/IdentityLecturesRollCallPart.java b/src/main/java/org/olat/modules/lecture/ui/coach/IdentityLecturesRollCallPart.java index 92e07ddc918e8a5af60bef998971f29eb3016819..982c3f18c19318406cb541fc5437e9fb3eeb1260 100644 --- a/src/main/java/org/olat/modules/lecture/ui/coach/IdentityLecturesRollCallPart.java +++ b/src/main/java/org/olat/modules/lecture/ui/coach/IdentityLecturesRollCallPart.java @@ -22,7 +22,6 @@ package org.olat.modules.lecture.ui.coach; import org.olat.modules.lecture.AbsenceNotice; import org.olat.modules.lecture.LectureBlock; import org.olat.modules.lecture.LectureBlockRollCall; -import org.olat.modules.lecture.LectureBlockStatus; import org.olat.modules.lecture.ui.component.LectureBlockRollCallStatusItem; import org.olat.modules.lecture.ui.component.RollCallItem; @@ -65,11 +64,7 @@ public class IdentityLecturesRollCallPart implements RollCallItem { @Override public int getPlannedLecturesNumber() { - int numOfLectures = lectureBlock.getEffectiveLecturesNumber(); - if(numOfLectures <= 0 && lectureBlock.getStatus() != LectureBlockStatus.cancelled) { - numOfLectures = lectureBlock.getPlannedLecturesNumber(); - } - return numOfLectures; + return lectureBlock.getCalculatedLecturesNumber(); } @Override diff --git a/src/main/java/org/olat/modules/lecture/ui/coach/LecturesCockpitController.java b/src/main/java/org/olat/modules/lecture/ui/coach/LecturesCockpitController.java index 72ad09b1a8eb433892452508071b58fa10cd912f..f66293c95aba17638781a671a2de0d2760c6e528 100644 --- a/src/main/java/org/olat/modules/lecture/ui/coach/LecturesCockpitController.java +++ b/src/main/java/org/olat/modules/lecture/ui/coach/LecturesCockpitController.java @@ -254,11 +254,8 @@ public class LecturesCockpitController extends BasicController implements Activa List<Link> pendingLinks = new ArrayList<>(); Set<String> deduplicate = new HashSet<>(); for(LectureBlock lectureBlock:lectureBlocks) { - int lectures = lectureBlock.getEffectiveLecturesNumber(); - if(lectures <= 0) { - lectures = lectureBlock.getPlannedLecturesNumber(); - } - + int lectures = lectureBlock.getCalculatedLecturesNumber(); + Date startdDate = lectureBlock.getStartDate(); String day = formatter.dayOfWeek(startdDate); String date = formatter.formatDate(startdDate); diff --git a/src/main/java/org/olat/modules/lecture/ui/component/DailyDateCellRenderer.java b/src/main/java/org/olat/modules/lecture/ui/component/DailyDateCellRenderer.java index 1f334309ffdaafc8cd3086faa543d14d7620bcac..2588e9153c5ce76cf2316af7d495e2945c904e32 100644 --- a/src/main/java/org/olat/modules/lecture/ui/component/DailyDateCellRenderer.java +++ b/src/main/java/org/olat/modules/lecture/ui/component/DailyDateCellRenderer.java @@ -21,6 +21,7 @@ package org.olat.modules.lecture.ui.component; import java.util.Date; +import java.util.List; import java.util.Locale; import org.olat.commons.calendar.CalendarUtils; @@ -31,9 +32,13 @@ 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.Formatter; +import org.olat.core.util.StringHelper; import org.olat.modules.lecture.AbsenceNotice; +import org.olat.modules.lecture.AbsenceNoticeTarget; +import org.olat.modules.lecture.LectureBlock; import org.olat.modules.lecture.model.AbsenceNoticeInfos; import org.olat.modules.lecture.ui.coach.AbsenceNoticeHelper; +import org.olat.modules.lecture.ui.coach.AbsenceNoticeRow; /** * Show the date focused on a daily base. The actual date is not shown, @@ -46,6 +51,7 @@ import org.olat.modules.lecture.ui.coach.AbsenceNoticeHelper; public class DailyDateCellRenderer implements FlexiCellRenderer { private Date currentDate; + private int counter = 0; private final Formatter format; private final Translator translator; @@ -62,42 +68,53 @@ public class DailyDateCellRenderer implements FlexiCellRenderer { @Override public void render(Renderer renderer, StringOutput target, Object cellValue, int row, FlexiTableComponent source, URLBuilder ubu, Translator transl) { - if(cellValue instanceof AbsenceNoticeInfos) { + if(cellValue instanceof AbsenceNoticeRow) { + AbsenceNoticeRow noticeRow = (AbsenceNoticeRow)cellValue; + render(target, noticeRow.getAbsenceNotice(), noticeRow.getLectureBlocks()); + } else if(cellValue instanceof AbsenceNoticeInfos) { AbsenceNoticeInfos infos = (AbsenceNoticeInfos)cellValue; - render(target, infos.getStartDate(), infos.getEndDate()); + render(target, infos.getAbsenceNotice(), null); } else if(cellValue instanceof AbsenceNotice) { AbsenceNotice notice = (AbsenceNotice)cellValue; - render(target, notice.getStartDate(), notice.getEndDate()); + render(target, notice, null); } } - private void render(StringOutput target, Date startDate, Date endDate) { + private boolean isRenderLectureBlock(AbsenceNotice notice, List<LectureBlock> lectures) { + return notice.getNoticeTarget() == AbsenceNoticeTarget.lectureblocks + && (lectures != null && !lectures.isEmpty()); + } + + private void render(StringOutput target, AbsenceNotice notice, List<LectureBlock> lectures) { + Date startDate = notice.getStartDate(); + Date endDate = notice.getEndDate(); + boolean startWholeDay = AbsenceNoticeHelper.isStartOfWholeDay(startDate); boolean endWholeDay = AbsenceNoticeHelper.isEndOfWholeDay(endDate); if(CalendarUtils.isSameDay(startDate, endDate)) { if(startWholeDay && endWholeDay) { - target.append(translator.translate("whole.day")); + renderWholeDay(target, notice, lectures); } else { renderSameDay(target, startDate, endDate); } } else if(startWholeDay && endWholeDay) { - target.append(translator.translate("whole.day")); + renderWholeDay(target, notice, lectures); } else if(currentDate != null) { if(CalendarUtils.isSameDay(currentDate, startDate)) { if(startWholeDay) { - target.append(translator.translate("whole.day")); + renderWholeDay(target, notice, lectures); } else { target.append(translator.translate("from", new String[] { format.formatTimeShort(startDate) })); } } else if(CalendarUtils.isSameDay(currentDate, endDate)) { if(endWholeDay) { - target.append(translator.translate("whole.day")); + renderWholeDay(target, notice, lectures); } else { target.append(translator.translate("upto", new String[] { format.formatTimeShort(endDate) })); } } else if(startDate.before(currentDate) && endDate.after(currentDate)) { - target.append(translator.translate("whole.day")); + renderWholeDay(target, notice, lectures); } else { renderError(target, startDate, endDate); } @@ -106,6 +123,14 @@ public class DailyDateCellRenderer implements FlexiCellRenderer { } } + private void renderWholeDay(StringOutput target, AbsenceNotice notice, List<LectureBlock> lectures) { + if(isRenderLectureBlock(notice, lectures)) { + renderLectures(target, lectures); + } else { + target.append(translator.translate("whole.day")); + } + } + private void renderError(StringOutput target, Date startDate, Date endDate) { boolean startWholeDay = AbsenceNoticeHelper.isStartOfWholeDay(startDate); boolean endWholeDay = AbsenceNoticeHelper.isEndOfWholeDay(endDate); @@ -150,6 +175,40 @@ public class DailyDateCellRenderer implements FlexiCellRenderer { } } + private void renderLectures(StringOutput target, List<LectureBlock> lectureBlocks) { + int numOfBlocks = lectureBlocks.size(); + int numOfLectures = 0; + for(LectureBlock lectureBlock:lectureBlocks) { + numOfLectures += lectureBlock.getCalculatedLecturesNumber(); + } + + String labelKey = numOfBlocks == 1 ? "table.lecture.infos" : "table.lectures.infos"; + String label = translator.translate(labelKey, new String[] { Integer.toString(numOfBlocks), Integer.toString(numOfLectures) }); + String id = "p_infos_" + ++counter; + target.append("<span>").append(label).append(" <i id='").append(id).append("' class='o_icon o_icon-lg o_icon_info'> </i></span>"); + + StringBuilder sb = new StringBuilder(); + sb.append("<ul class='list-unstyled'>"); + for(LectureBlock lectureBlock:lectureBlocks) { + sb.append("<li>").append(getLectureBlockLabel(lectureBlock)).append("</li>"); + } + sb.append("</ul>"); + target.append("<script>jQuery(function () {jQuery('#").append(id).append("').tooltip({placement:\"bottom\",container: \"body\",html:true,title:\"") + .append(StringHelper.escapeJavaScript(sb.toString())) + .append("\"});})</script>"); + } - + private String getLectureBlockLabel(LectureBlock block) { + int numOfLectures = block.getCalculatedLecturesNumber(); + String[] args = new String[] { + format.formatDate(block.getStartDate()), // 0 + format.formatTimeShort(block.getStartDate()), // 1 + format.formatTimeShort(block.getEndDate()), // 2 + Integer.toString(numOfLectures), // 3 + StringHelper.escapeHtml(block.getTitle()), // 4 + }; + + String key = numOfLectures <= 1 ? "table.lecture.explain" : "table.lectures.explain"; + return translator.translate(key, args); + } } diff --git a/src/main/java/org/olat/modules/lecture/ui/component/StartEndDateCellRenderer.java b/src/main/java/org/olat/modules/lecture/ui/component/StartEndDateCellRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..bbf06a3ce256c519b979e9549e1ad317be881a6b --- /dev/null +++ b/src/main/java/org/olat/modules/lecture/ui/component/StartEndDateCellRenderer.java @@ -0,0 +1,89 @@ +/** + * <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.modules.lecture.ui.component; + +import java.util.Date; +import java.util.Locale; + +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponent; +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.Formatter; +import org.olat.modules.lecture.AbsenceNoticeTarget; +import org.olat.modules.lecture.LectureBlock; +import org.olat.modules.lecture.ui.coach.AbsenceNoticeHelper; +import org.olat.modules.lecture.ui.coach.AbsenceNoticeRow; + +/** + * + * Initial date: 14 mai 2020<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class StartEndDateCellRenderer implements FlexiCellRenderer { + + private final boolean startDate; + private final Formatter formatter; + + public StartEndDateCellRenderer(boolean startDate, Locale locale) { + this.startDate = startDate; + formatter = Formatter.getInstance(locale); + } + + @Override + public void render(Renderer renderer, StringOutput target, Object cellValue, int row, FlexiTableComponent source, + URLBuilder ubu, Translator translator) { + + Object obj = source.getFlexiTableElement().getTableDataModel().getObject(row); + if(obj instanceof AbsenceNoticeRow) { + AbsenceNoticeRow noticeRow = (AbsenceNoticeRow)obj; + + Date date = null; + if(noticeRow.getAbsenceNotice().getNoticeTarget() == AbsenceNoticeTarget.lectureblocks + && (noticeRow.getLectureBlocks() != null && !noticeRow.getLectureBlocks().isEmpty())) { + if(startDate) { + date = noticeRow.getLectureBlocks().stream() + .map(LectureBlock::getStartDate) + .min(Date::compareTo) + .orElse(null); + } else { + date = noticeRow.getLectureBlocks().stream() + .map(LectureBlock::getEndDate) + .max(Date::compareTo) + .orElse(null); + } + } else { + date = startDate ? noticeRow.getStartDate() : noticeRow.getEndDate(); + } + + if(date != null) { + if((startDate && AbsenceNoticeHelper.isStartOfWholeDay(date)) + || (!startDate && AbsenceNoticeHelper.isEndOfWholeDay(date))) { + target.append(formatter.formatDate(date)); + } else { + target.append(formatter.formatDateAndTime(date)); + } + } + } + } +} diff --git a/src/main/java/org/olat/modules/lecture/ui/export/LecturesBlockPDFExport.java b/src/main/java/org/olat/modules/lecture/ui/export/LecturesBlockPDFExport.java index d1d8f348c824733bdef439e9ddcd9dcd291d90c4..112a496cfbf016acac135398deb509b7419a6fa9 100644 --- a/src/main/java/org/olat/modules/lecture/ui/export/LecturesBlockPDFExport.java +++ b/src/main/java/org/olat/modules/lecture/ui/export/LecturesBlockPDFExport.java @@ -78,10 +78,7 @@ public class LecturesBlockPDFExport extends PdfDocument implements MediaResource this.lectureBlock = lectureBlock; this.authorizedAbsenceEnabled = authorizedAbsenceEnabled; - numOfLectures = lectureBlock.getEffectiveLecturesNumber(); - if(numOfLectures <= 0) { - numOfLectures = lectureBlock.getPlannedLecturesNumber(); - } + numOfLectures = lectureBlock.getCalculatedLecturesNumber(); } public String getTeacher() { @@ -253,7 +250,7 @@ public class LecturesBlockPDFExport extends PdfDocument implements MediaResource if(rollCall.getLecturesAbsentList() != null) { List<Integer> absenceList = rollCall.getLecturesAbsentList(); for(int j=0; j<numOfLectures; j++) { - absences[j] = absenceList.contains(new Integer(j)); + absences[j] = absenceList.contains(Integer.valueOf(j)); } } if(rollCall.getAbsenceAuthorized() != null) {