Index: lams_central/web/css/components.css =================================================================== diff -u -rff9f51378eb2ac41ff5c96ba9263f1d51b37a075 -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_central/web/css/components.css (.../components.css) (revision ff9f51378eb2ac41ff5c96ba9263f1d51b37a075) +++ lams_central/web/css/components.css (.../components.css) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -93,7 +93,8 @@ border-bottom: 2px solid #20639B; } -.component-page-wrapper table.table tbody td { +.component-page-wrapper table.table tbody td, +.component-page-wrapper table.table tbody th { border: none; border-bottom: 2px solid #C3CEDC; } Index: lams_central/web/css/vertical-timeline.css =================================================================== diff -u -r7ecadc30076e09aa7a50a2c495344c56622f5105 -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_central/web/css/vertical-timeline.css (.../vertical-timeline.css) (revision 7ecadc30076e09aa7a50a2c495344c56622f5105) +++ lams_central/web/css/vertical-timeline.css (.../vertical-timeline.css) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -160,21 +160,21 @@ margin: 5px 0 0 10px; } -.vertical-timeline .timeline-entry .timeline-entry-inner .timeline-icon.bg-success ~ .timeline-label:after { +.vertical-timeline .timeline-entry .timeline-entry-inner .timeline-icon.activity-complete ~ .timeline-label:after { margin-left: -13px; border-color: transparent var(--bs-success) transparent transparent; } -.vertical-timeline .timeline-entry .timeline-entry-inner .timeline-icon.bg-success ~ .timeline-label{ +.vertical-timeline .timeline-entry .timeline-entry-inner .timeline-icon.activity-complete ~ .timeline-label{ border-left: thick solid var(--bs-success); } -.vertical-timeline .timeline-entry .timeline-entry-inner .timeline-icon.bg-primary ~ .timeline-label:after { +.vertical-timeline .timeline-entry .timeline-entry-inner .timeline-icon.activity-current ~ .timeline-label:after { margin-left: -13px; border-color: transparent var(--bs-primary) transparent transparent; } -.vertical-timeline .timeline-entry .timeline-entry-inner .timeline-icon.bg-primary ~ .timeline-label{ +.vertical-timeline .timeline-entry .timeline-entry-inner .timeline-icon.activity-current ~ .timeline-label{ border-left: thick solid var(--bs-primary); } Index: lams_common/src/java/org/lamsfoundation/lams/learningdesign/dto/ActivityURL.java =================================================================== diff -u -rf4502360cd44d86d57b095aea5aef7ce663c8b61 -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_common/src/java/org/lamsfoundation/lams/learningdesign/dto/ActivityURL.java (.../ActivityURL.java) (revision f4502360cd44d86d57b095aea5aef7ce663c8b61) +++ lams_common/src/java/org/lamsfoundation/lams/learningdesign/dto/ActivityURL.java (.../ActivityURL.java) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -21,7 +21,6 @@ * **************************************************************** */ - package org.lamsfoundation.lams.learningdesign.dto; import java.util.List; @@ -41,12 +40,14 @@ private String type; private Long activityId; private String url; + private String iconURL; private String title; private String description; private boolean complete; private boolean floating; private byte status; private boolean defaultURL; + private long duration; private List childActivities; public ActivityURL() { @@ -110,6 +111,14 @@ this.url = url; } + public String getIconURL() { + return iconURL; + } + + public void setIconURL(String iconURL) { + this.iconURL = iconURL; + } + public String getDescription() { return description; } @@ -134,6 +143,14 @@ this.status = status; } + public Long getDuration() { + return duration; + } + + public void setDuration(Long duration) { + this.duration = duration; + } + /** Get a list of the urls for the child activities. Only used on the jsp progress display page */ public List getChildActivities() { return childActivities; @@ -148,5 +165,4 @@ return new ToStringBuilder(this).append("activityId", activityId).append("title", title).append("url", url) .toString(); } - -} +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/lesson/util/LessonUtil.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/lesson/util/LessonUtil.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/lesson/util/LessonUtil.java (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -0,0 +1,41 @@ +package org.lamsfoundation.lams.lesson.util; + +import java.util.Date; + +import org.lamsfoundation.lams.learningdesign.Activity; +import org.lamsfoundation.lams.lesson.CompletedActivityProgress; +import org.lamsfoundation.lams.lesson.CompletedActivityProgressArchive; +import org.lamsfoundation.lams.lesson.LearnerProgress; +import org.lamsfoundation.lams.lesson.LearnerProgressArchive; + +public class LessonUtil { + + public static Long getActivityDuration(Object learnerProgress, Activity activity) { + if (learnerProgress != null) { + // this construct looks bad but see LDEV-4609 commit for explanation + if (learnerProgress instanceof LearnerProgressArchive) { + CompletedActivityProgressArchive compProg = ((LearnerProgressArchive) learnerProgress) + .getCompletedActivities().get(activity); + if (compProg != null) { + Date startTime = compProg.getStartDate(); + Date endTime = compProg.getFinishDate(); + if ((startTime != null) && (endTime != null)) { + return endTime.getTime() - startTime.getTime(); + } + } + } else { + CompletedActivityProgress compProg = ((LearnerProgress) learnerProgress).getCompletedActivities() + .get(activity); + if (compProg != null) { + Date startTime = compProg.getStartDate(); + Date endTime = compProg.getFinishDate(); + if ((startTime != null) && (endTime != null)) { + return endTime.getTime() - startTime.getTime(); + } + } + } + + } + return null; + } +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/tool/service/ILamsCoreToolService.java =================================================================== diff -u -r02ce40b60524aa33d326fbda824dcd43f566ab94 -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_common/src/java/org/lamsfoundation/lams/tool/service/ILamsCoreToolService.java (.../ILamsCoreToolService.java) (revision 02ce40b60524aa33d326fbda824dcd43f566ab94) +++ lams_common/src/java/org/lamsfoundation/lams/tool/service/ILamsCoreToolService.java (.../ILamsCoreToolService.java) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -320,6 +320,8 @@ */ Long getActivityMaxPossibleMark(ToolActivity activity); + Long getActivityMaxPossibleMark(long toolActivityId); + /** * Calculates lesson's maximum possible mark by adding up all activities max marks. * Index: lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsCoreToolService.java =================================================================== diff -u -r3085af1c7e3e6c3496af23a748d998886d7168fd -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsCoreToolService.java (.../LamsCoreToolService.java) (revision 3085af1c7e3e6c3496af23a748d998886d7168fd) +++ lams_common/src/java/org/lamsfoundation/lams/tool/service/LamsCoreToolService.java (.../LamsCoreToolService.java) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -710,6 +710,12 @@ } } + public Long getActivityMaxPossibleMark(long toolActivityId) { + ToolActivity toolActivity = (ToolActivity) activityDAO.getActivityByActivityId(toolActivityId, + ToolActivity.class); + return getActivityMaxPossibleMark(toolActivity); + } + @Override public Long getActivityMaxPossibleMark(ToolActivity activity) { // if ActivityEvaluation is not set it means activity will produce no toolOutputs and thus max possible mark is null Index: lams_common/src/java/org/lamsfoundation/lams/util/DateUtil.java =================================================================== diff -u -reeaec5d1e9dedb2349cabff878dfae20be73c585 -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_common/src/java/org/lamsfoundation/lams/util/DateUtil.java (.../DateUtil.java) (revision eeaec5d1e9dedb2349cabff878dfae20be73c585) +++ lams_common/src/java/org/lamsfoundation/lams/util/DateUtil.java (.../DateUtil.java) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -54,9 +54,13 @@ public static final String SCHEDULE_LESSON_FORMAT = "dd/M/yyyy h:mm a"; public static final String ISO8601_FORMAT = "yyyy-MM-dd'T'HH:mmZ"; public static final String PRETTY_FORMAT = "d MMMM yyyy h:mm:ss a"; - - private static final FastDateFormat dateFormatterTimeAgo = FastDateFormat.getInstance(DateUtil.ISO8601_FORMAT, TimeZone.getTimeZone("GMT"), null); + private static final DateFormat shortDateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, + DateFormat.SHORT); + + private static final FastDateFormat dateFormatterTimeAgo = FastDateFormat.getInstance(DateUtil.ISO8601_FORMAT, + TimeZone.getTimeZone("GMT"), null); + /** * Convert your local time to Universal Time Coordinator. TODO conversion is not working properly. The returned Date * object still contain server local timezone rather than GMT time zone. @@ -105,7 +109,7 @@ */ public static Date convertToTimeZoneFromDefault(TimeZone targetTimeZone, Date date) { TimeZone defaultTz = TimeZone.getDefault(); - Integer rawOffset = defaultTz.getOffset(date.getTime()) - targetTimeZone.getOffset(date.getTime()); + int rawOffset = defaultTz.getOffset(date.getTime()) - targetTimeZone.getOffset(date.getTime()); return new Date(date.getTime() - rawOffset); } @@ -121,7 +125,7 @@ */ public static Date convertFromTimeZoneToDefault(TimeZone targetTimeZone, Date date) { TimeZone defaultTz = TimeZone.getDefault(); - Integer rawOffset = defaultTz.getOffset(date.getTime()) - targetTimeZone.getOffset(date.getTime()); + int rawOffset = defaultTz.getOffset(date.getTime()) - targetTimeZone.getOffset(date.getTime()); return new Date(date.getTime() + rawOffset); } @@ -267,7 +271,60 @@ */ public static String convertToStringForTimeagoJSON(Date value) { return dateFormatterTimeAgo.format(value); - + } + /** + * A shared function to convert milliseconds into a readable string + * + * @param timeInMillis + * @return + */ + public static String convertTimeToString(Long timeInMillis) { + StringBuilder sb = new StringBuilder(); + if (timeInMillis != null && timeInMillis >= 1000) { + long totalTimeInSeconds = timeInMillis / 1000; + + long seconds = (totalTimeInSeconds >= 60 ? totalTimeInSeconds % 60 : totalTimeInSeconds); + long minutes = (totalTimeInSeconds = (totalTimeInSeconds / 60)) >= 60 ? totalTimeInSeconds % 60 + : totalTimeInSeconds; + long hours = (totalTimeInSeconds = (totalTimeInSeconds / 60)) >= 24 ? totalTimeInSeconds % 24 + : totalTimeInSeconds; + long days = (totalTimeInSeconds = (totalTimeInSeconds / 24)); + + if (days != 0) { + sb.append("" + days + "d, "); + } + if (hours != 0) { + sb.append("" + hours + "h, "); + } + if (minutes != 0) { + sb.append("" + minutes + "m, "); + } + if (seconds != 0) { + sb.append("" + seconds + "s"); + } + } + + if (sb.length() > 0) { + return sb.toString(); + } else { + return null; + } + } + + /** + * A shared function to convert date into a readable string + * + * @param date + * to format + * @return formatted date + */ + public static String convertToString(Date date, DateFormat format) { + if (date != null) { + DateFormat usedFormat = format == null ? shortDateFormat : format; + return usedFormat.format(date); + } + return null; + } } Index: lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBActivityArchiveGridRowDTO.java =================================================================== diff -u -rd80d90361b631c959813fa15568d73c7b5a44bd7 -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBActivityArchiveGridRowDTO.java (.../GBActivityArchiveGridRowDTO.java) (revision d80d90361b631c959813fa15568d73c7b5a44bd7) +++ lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBActivityArchiveGridRowDTO.java (.../GBActivityArchiveGridRowDTO.java) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -26,6 +26,7 @@ import org.lamsfoundation.lams.gradebook.util.GBGridView; import org.lamsfoundation.lams.gradebook.util.GradebookUtil; +import org.lamsfoundation.lams.util.DateUtil; public class GBActivityArchiveGridRowDTO extends GradebookGridRowDTO { @@ -44,16 +45,16 @@ ret.add(feedback); ret.add(lessonMark.toString()); ret.add(status); - ret.add(timeTaken != null ? convertTimeToString(timeTaken) : CELL_EMPTY); - ret.add(startDate != null ? convertDateToString(startDate, null) : CELL_EMPTY); - ret.add(finishDate != null ? convertDateToString(finishDate, null) : CELL_EMPTY); + ret.add(timeTaken != null ? DateUtil.convertTimeToString(timeTaken) : CELL_EMPTY); + ret.add(startDate != null ? DateUtil.convertToString(startDate, null) : CELL_EMPTY); + ret.add(finishDate != null ? DateUtil.convertToString(finishDate, null) : CELL_EMPTY); ret.add(mark != null ? GradebookUtil.niceFormatting(mark) : CELL_EMPTY); } else { ret.add(id); ret.add(status); - ret.add(timeTaken != null ? convertTimeToString(timeTaken) : CELL_EMPTY); - ret.add(startDate != null ? convertDateToString(startDate, null) : CELL_EMPTY); - ret.add(finishDate != null ? convertDateToString(finishDate, null) : CELL_EMPTY); + ret.add(timeTaken != null ? DateUtil.convertTimeToString(timeTaken) : CELL_EMPTY); + ret.add(startDate != null ? DateUtil.convertToString(startDate, null) : CELL_EMPTY); + ret.add(finishDate != null ? DateUtil.convertToString(finishDate, null) : CELL_EMPTY); ret.add(feedback); ret.add(lessonMark != null ? GradebookUtil.niceFormatting(lessonMark) : CELL_EMPTY); ret.add(mark != null ? GradebookUtil.niceFormatting(mark) : CELL_EMPTY); Index: lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBActivityGridRowDTO.java =================================================================== diff -u -r96033f32ff880d045b4c087f52628d233dc98095 -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBActivityGridRowDTO.java (.../GBActivityGridRowDTO.java) (revision 96033f32ff880d045b4c087f52628d233dc98095) +++ lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBActivityGridRowDTO.java (.../GBActivityGridRowDTO.java) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -32,6 +32,7 @@ import org.lamsfoundation.lams.learningdesign.CompetenceMapping; import org.lamsfoundation.lams.learningdesign.ToolActivity; import org.lamsfoundation.lams.usermanagement.service.UserManagementService; +import org.lamsfoundation.lams.util.DateUtil; import org.springframework.web.util.HtmlUtils; public class GBActivityGridRowDTO extends GradebookGridRowDTO { @@ -136,9 +137,9 @@ ret.add(rowName); } ret.add(status); - ret.add(timeTaken != null ? convertTimeToString(timeTaken) : CELL_EMPTY); - ret.add(startDate != null ? convertDateToString(startDate, null) : CELL_EMPTY); - ret.add(finishDate != null ? convertDateToString(finishDate, null) : CELL_EMPTY); + ret.add(timeTaken != null ? DateUtil.convertTimeToString(timeTaken) : CELL_EMPTY); + ret.add(startDate != null ? DateUtil.convertToString(startDate, null) : CELL_EMPTY); + ret.add(finishDate != null ? DateUtil.convertToString(finishDate, null) : CELL_EMPTY); ret.add(feedback); ret.add(outcomes != null ? outcomes : CELL_EMPTY); ret.add(mark != null ? GradebookUtil.niceFormatting(mark) : CELL_EMPTY); @@ -154,7 +155,7 @@ ret.add(rowName); } - ret.add((medianTimeTaken != null) ? convertTimeToString(medianTimeTaken) : CELL_EMPTY); + ret.add((medianTimeTaken != null) ? DateUtil.convertTimeToString(medianTimeTaken) : CELL_EMPTY); ret.add(CELL_EMPTY); ret.add(CELL_EMPTY); ret.add(competences); @@ -164,8 +165,8 @@ ret.add(rowName); ret.add(status); ret.add(feedback); - ret.add((medianTimeTaken != null) ? convertTimeToString(medianTimeTaken) : CELL_EMPTY); - ret.add((timeTaken != null) ? convertTimeToString(timeTaken) : CELL_EMPTY); + ret.add((medianTimeTaken != null) ? DateUtil.convertTimeToString(medianTimeTaken) : CELL_EMPTY); + ret.add((timeTaken != null) ? DateUtil.convertTimeToString(timeTaken) : CELL_EMPTY); ret.add(averageMark != null ? GradebookUtil.niceFormatting(averageMark) : CELL_EMPTY); ret.add(mark != null ? GradebookUtil.niceFormatting(mark) : CELL_EMPTY); Index: lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBLessonGridRowDTO.java =================================================================== diff -u -rc66eb16fd82d488f15aadc9c4c3d615b4493b12e -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBLessonGridRowDTO.java (.../GBLessonGridRowDTO.java) (revision c66eb16fd82d488f15aadc9c4c3d615b4493b12e) +++ lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBLessonGridRowDTO.java (.../GBLessonGridRowDTO.java) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -20,13 +20,13 @@ * **************************************************************** */ - package org.lamsfoundation.lams.gradebook.dto; import java.util.ArrayList; import org.lamsfoundation.lams.gradebook.util.GBGridView; import org.lamsfoundation.lams.gradebook.util.GradebookUtil; +import org.lamsfoundation.lams.util.DateUtil; import org.springframework.web.util.HtmlUtils; public class GBLessonGridRowDTO extends GradebookGridRowDTO { @@ -49,7 +49,7 @@ @Override public ArrayList toStringArray(GBGridView view) { - ArrayList ret = new ArrayList(); + ArrayList ret = new ArrayList<>(); ret.add(id.toString()); @@ -63,10 +63,11 @@ ret.add(rowName); } ret.add(subGroup); - ret.add(startDate != null ? convertDateToString(startDate, null) : CELL_EMPTY); - ret.add((medianTimeTaken != null && medianTimeTaken != 0) ? convertTimeToString(medianTimeTaken) + ret.add(startDate != null ? DateUtil.convertToString(startDate, null) : CELL_EMPTY); + ret.add((medianTimeTaken != null && medianTimeTaken != 0) ? DateUtil.convertTimeToString(medianTimeTaken) : CELL_EMPTY); - ret.add((averageMark != null) ? GradebookUtil.niceFormatting(averageMark, displayMarkAsPercent) : CELL_EMPTY); + ret.add((averageMark != null) ? GradebookUtil.niceFormatting(averageMark, displayMarkAsPercent) + : CELL_EMPTY); } else if ((view == GBGridView.LRN_COURSE) || (view == GBGridView.MON_USER)) { if (gradebookLearnerURL != null && gradebookLearnerURL.length() != 0) { @@ -77,13 +78,15 @@ } ret.add(subGroup); ret.add((status != null) ? status : CELL_EMPTY); - ret.add(startDate != null ? convertDateToString(startDate, null) : CELL_EMPTY); - ret.add(finishDate != null ? convertDateToString(finishDate, null) : CELL_EMPTY); + ret.add(startDate != null ? DateUtil.convertToString(startDate, null) : CELL_EMPTY); + ret.add(finishDate != null ? DateUtil.convertToString(finishDate, null) : CELL_EMPTY); ret.add(feedback); ret.add((medianTimeTaken != null && medianTimeTaken != 0) - ? toItalic(convertTimeToString(medianTimeTaken)) : CELL_EMPTY); - ret.add((timeTaken != null) ? convertTimeToString(timeTaken) : CELL_EMPTY); - ret.add((averageMark != null) ? toItalic(GradebookUtil.niceFormatting(averageMark, displayMarkAsPercent)) : CELL_EMPTY); + ? toItalic(DateUtil.convertTimeToString(medianTimeTaken)) + : CELL_EMPTY); + ret.add((timeTaken != null) ? DateUtil.convertTimeToString(timeTaken) : CELL_EMPTY); + ret.add((averageMark != null) ? toItalic(GradebookUtil.niceFormatting(averageMark, displayMarkAsPercent)) + : CELL_EMPTY); ret.add((mark != null) ? GradebookUtil.niceFormatting(mark, displayMarkAsPercent) : CELL_EMPTY); //plain lesson list case Index: lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBUserGridRowDTO.java =================================================================== diff -u -r365a2c22199a5fe2b1e55e18cbf4b6d2596f202b -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBUserGridRowDTO.java (.../GBUserGridRowDTO.java) (revision 365a2c22199a5fe2b1e55e18cbf4b6d2596f202b) +++ lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GBUserGridRowDTO.java (.../GBUserGridRowDTO.java) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -27,6 +27,7 @@ import org.lamsfoundation.lams.gradebook.util.GBGridView; import org.lamsfoundation.lams.gradebook.util.GradebookUtil; import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.util.DateUtil; import org.springframework.web.util.HtmlUtils; public class GBUserGridRowDTO extends GradebookGridRowDTO { @@ -67,9 +68,9 @@ ret.add(rowName); ret.add(status); - ret.add((timeTaken != null) ? convertTimeToString(timeTaken) : CELL_EMPTY); - ret.add(startDate != null ? convertDateToString(startDate, null) : CELL_EMPTY); - ret.add(finishDate != null ? convertDateToString(finishDate, null) : CELL_EMPTY); + ret.add((timeTaken != null) ? DateUtil.convertTimeToString(timeTaken) : CELL_EMPTY); + ret.add(startDate != null ? DateUtil.convertToString(startDate, null) : CELL_EMPTY); + ret.add(finishDate != null ? DateUtil.convertToString(finishDate, null) : CELL_EMPTY); ret.add(feedback); ret.add((mark != null) ? GradebookUtil.niceFormatting(mark, displayMarkAsPercent) : CELL_EMPTY); ret.add(portraitId != null ? portraitId.toString() : ""); @@ -80,9 +81,9 @@ ret.add(marksAvailable != null ? marksAvailable.toString() : ""); ret.add(rowName); ret.add(status); - ret.add((timeTaken != null) ? convertTimeToString(timeTaken) : CELL_EMPTY); - ret.add(startDate != null ? convertDateToString(startDate, null) : CELL_EMPTY); - ret.add(finishDate != null ? convertDateToString(finishDate, null) : CELL_EMPTY); + ret.add((timeTaken != null) ? DateUtil.convertTimeToString(timeTaken) : CELL_EMPTY); + ret.add(startDate != null ? DateUtil.convertToString(startDate, null) : CELL_EMPTY); + ret.add(finishDate != null ? DateUtil.convertToString(finishDate, null) : CELL_EMPTY); ret.add(feedback); ret.add((mark != null) ? GradebookUtil.niceFormatting(mark) : CELL_EMPTY); ret.add(portraitId != null ? portraitId.toString() : ""); @@ -94,9 +95,9 @@ } else if (view == GBGridView.MON_COURSE) { ret.add(rowName); ret.add(status); - ret.add((timeTaken != null) ? convertTimeToString(timeTaken) : CELL_EMPTY); - ret.add(startDate != null ? convertDateToString(startDate, null) : CELL_EMPTY); - ret.add(finishDate != null ? convertDateToString(finishDate, null) : CELL_EMPTY); + ret.add((timeTaken != null) ? DateUtil.convertTimeToString(timeTaken) : CELL_EMPTY); + ret.add(startDate != null ? DateUtil.convertToString(startDate, null) : CELL_EMPTY); + ret.add(finishDate != null ? DateUtil.convertToString(finishDate, null) : CELL_EMPTY); ret.add(feedback); ret.add((mark != null) ? GradebookUtil.niceFormatting(mark, displayMarkAsPercent) : CELL_EMPTY); ret.add(portraitId != null ? portraitId.toString() : ""); Index: lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GradebookGridRowDTO.java =================================================================== diff -u -r62aaf160878735888d077bf28fac3c1989bb8fbd -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GradebookGridRowDTO.java (.../GradebookGridRowDTO.java) (revision 62aaf160878735888d077bf28fac3c1989bb8fbd) +++ lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/dto/GradebookGridRowDTO.java (.../GradebookGridRowDTO.java) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -22,7 +22,6 @@ package org.lamsfoundation.lams.gradebook.dto; -import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; @@ -34,9 +33,6 @@ protected static final String CELL_EMPTY = "-"; - protected static final DateFormat DEFAULT_DATE_FORMAT = DateFormat.getDateTimeInstance(DateFormat.SHORT, - DateFormat.SHORT); - // The id for a row, might be activityId, userId, lessonID etc protected String id; @@ -78,60 +74,6 @@ protected boolean displayMarkAsPercent = false; - /** - * A shared function to convert milliseconds into a readable string - * - * @param timeInMillis - * @return - */ - protected String convertTimeToString(Long timeInMillis) { - StringBuilder sb = new StringBuilder(); - if (timeInMillis != null && timeInMillis > 1000) { - long totalTimeInSeconds = timeInMillis / 1000; - - long seconds = (totalTimeInSeconds >= 60 ? totalTimeInSeconds % 60 : totalTimeInSeconds); - long minutes = (totalTimeInSeconds = (totalTimeInSeconds / 60)) >= 60 ? totalTimeInSeconds % 60 - : totalTimeInSeconds; - long hours = (totalTimeInSeconds = (totalTimeInSeconds / 60)) >= 24 ? totalTimeInSeconds % 24 - : totalTimeInSeconds; - long days = (totalTimeInSeconds = (totalTimeInSeconds / 24)); - - if (days != 0) { - sb.append("" + days + "d, "); - } - if (hours != 0) { - sb.append("" + hours + "h, "); - } - if (minutes != 0) { - sb.append("" + minutes + "m, "); - } - if (seconds != 0) { - sb.append("" + seconds + "s"); - } - } - - if (sb.length() > 0) { - return sb.toString(); - } else { - return null; - } - } - - /** - * A shared function to convert date into a readable string - * - * @param date - * to format - * @return formatted date - */ - protected String convertDateToString(Date date, DateFormat format) { - if (date != null) { - DateFormat usedFormat = format == null ? DEFAULT_DATE_FORMAT : format; - return usedFormat.format(date); - } - return null; - } - protected String toItalic(String string) { return "" + string + ""; } Index: lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/service/GradebookService.java =================================================================== diff -u -rcde8c481e618581dcb2279191ef0b163e9abb80b -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/service/GradebookService.java (.../GradebookService.java) (revision cde8c481e618581dcb2279191ef0b163e9abb80b) +++ lams_gradebook/src/java/org/lamsfoundation/lams/gradebook/service/GradebookService.java (.../GradebookService.java) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -82,6 +82,7 @@ import org.lamsfoundation.lams.lesson.dao.ILearnerProgressDAO; import org.lamsfoundation.lams.lesson.dao.ILessonDAO; import org.lamsfoundation.lams.lesson.service.ILessonService; +import org.lamsfoundation.lams.lesson.util.LessonUtil; import org.lamsfoundation.lams.logevent.LogEvent; import org.lamsfoundation.lams.logevent.service.ILogEventService; import org.lamsfoundation.lams.outcome.Outcome; @@ -212,7 +213,7 @@ // Setting status activityDTO.setStartDate(getActivityStartDate(learnerProgress, activity, userTimezone)); activityDTO.setFinishDate(getActivityFinishDate(learnerProgress, activity, userTimezone)); - activityDTO.setTimeTaken(getActivityDuration(learnerProgress, activity)); + activityDTO.setTimeTaken(LessonUtil.getActivityDuration(learnerProgress, activity)); activityDTO.setStatus(getActivityStatusStr(learnerProgress, activity)); // Setting averages @@ -291,7 +292,7 @@ // Setting status activityDTO.setStartDate(getActivityStartDate(learnerProgress, activity, userTimezone)); activityDTO.setFinishDate(getActivityFinishDate(learnerProgress, activity, userTimezone)); - activityDTO.setTimeTaken(getActivityDuration(learnerProgress, activity)); + activityDTO.setTimeTaken(LessonUtil.getActivityDuration(learnerProgress, activity)); activityDTO.setStatus(getActivityStatusStr(learnerProgress, activity)); for (GradebookUserActivityArchive activityArchive : activityArchives) { @@ -430,7 +431,7 @@ // Set the progress LearnerProgress learnerProgress = userToLearnerProgressMap.get(learner.getUserId()); gUserDTO.setStatus(getActivityStatusStr(learnerProgress, activity)); - gUserDTO.setTimeTaken(getActivityDuration(learnerProgress, activity)); + gUserDTO.setTimeTaken(LessonUtil.getActivityDuration(learnerProgress, activity)); gUserDTO.setStartDate(getActivityStartDate(learnerProgress, activity, timezone)); gUserDTO.setFinishDate(getActivityFinishDate(learnerProgress, activity, timezone)); @@ -1396,7 +1397,7 @@ // Set the progress LearnerProgress learnerProgress = userToLearnerProgressMap.get(learner.getUserId()); - userDTO.setTimeTaken(getActivityDuration(learnerProgress, toolActivity)); + userDTO.setTimeTaken(LessonUtil.getActivityDuration(learnerProgress, toolActivity)); userDTO.setStartDate(getActivityStartDate(learnerProgress, toolActivity, null)); userDTO.setFinishDate(getActivityFinishDate(learnerProgress, toolActivity, null)); @@ -1741,7 +1742,7 @@ Date finishDate = getActivityFinishDate(learnerProgress, activity, null); activityDataRow.addCell(finishDate == null ? "" : FileUtil.EXPORT_TO_SPREADSHEET_TITLE_DATE_FORMAT.format(finishDate)); - Long duration = getActivityDuration(learnerProgress, activity); + Long duration = LessonUtil.getActivityDuration(learnerProgress, activity); activityDataRow.addCell(duration == null ? "" : duration / 1000); activityDataRow.addCell(activityArchive == null ? "" : activityArchive.getMark(), false); } @@ -2644,35 +2645,6 @@ return finishDate; } - private Long getActivityDuration(Object learnerProgress, Activity activity) { - if (learnerProgress != null) { - // this construct looks bad but see LDEV-4609 commit for explanation - if (learnerProgress instanceof LearnerProgressArchive) { - CompletedActivityProgressArchive compProg = ((LearnerProgressArchive) learnerProgress) - .getCompletedActivities().get(activity); - if (compProg != null) { - Date startTime = compProg.getStartDate(); - Date endTime = compProg.getFinishDate(); - if ((startTime != null) && (endTime != null)) { - return endTime.getTime() - startTime.getTime(); - } - } - } else { - CompletedActivityProgress compProg = ((LearnerProgress) learnerProgress).getCompletedActivities() - .get(activity); - if (compProg != null) { - Date startTime = compProg.getStartDate(); - Date endTime = compProg.getFinishDate(); - if ((startTime != null) && (endTime != null)) { - return endTime.getTime() - startTime.getTime(); - } - } - } - - } - return null; - } - /** * Returns the lesson status string which is a reference to an image * Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/LearnerController.java =================================================================== diff -u -r2b597b0a7065de9c0d4fe6ab70273268afd01f8d -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/LearnerController.java (.../LearnerController.java) (revision 2b597b0a7065de9c0d4fe6ab70273268afd01f8d) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/controller/LearnerController.java (.../LearnerController.java) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -39,8 +39,8 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.lamsfoundation.lams.gradebook.GradebookUserActivity; import org.lamsfoundation.lams.gradebook.service.IGradebookService; import org.lamsfoundation.lams.learning.presence.PresenceWebsocketServer; import org.lamsfoundation.lams.learning.service.ILearnerFullService; @@ -59,6 +59,7 @@ import org.lamsfoundation.lams.lesson.service.ILessonService; import org.lamsfoundation.lams.monitoring.service.IMonitoringService; import org.lamsfoundation.lams.tool.ToolSession; +import org.lamsfoundation.lams.tool.service.ILamsCoreToolService; import org.lamsfoundation.lams.tool.service.ILamsToolService; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; @@ -114,6 +115,8 @@ @Autowired private ILamsToolService lamsToolService; @Autowired + private ILamsCoreToolService lamsCoreToolService; + @Autowired @Qualifier("learningMessageService") private MessageService messageService; @Autowired @@ -371,7 +374,8 @@ ObjectNode activityJSON = JsonNodeFactory.instance.objectNode(); activityJSON.put("id", activity.getActivityId()); activityJSON.put("name", activity.getTitle()); - activityJSON.put("status", activity.getActivityId().equals(currentActivityId) ? 0 : activity.getStatus()); + int status = activity.getActivityId().equals(currentActivityId) ? 0 : activity.getStatus(); + activityJSON.put("status", status); // URL in learner mode String url = activity.getUrl(); @@ -402,16 +406,31 @@ type = "o"; } else if (actType.contains("branching")) { type = "b"; + } else { + if (activity.getIconURL() != null) { + activityJSON.put("iconURL", activity.getIconURL()); + } + + if (status == 1) { + GradebookUserActivity activityMark = gradebookService.getGradebookUserActivity(activity.getActivityId(), + learnerId); + if (activityMark != null && activityMark.getMark() != null) { + activityJSON.put("mark", activityMark.getMark()); + } + } } - activityJSON.put("type", type); - // temporary code for monitoring UI upgrade - Activity activityObject = (Activity) userManagementService.findById(Activity.class, activity.getActivityId()); - if (StringUtils.isNotBlank(activityObject.getLibraryActivityUiImage())) { - activityJSON.put("iconURL", activityObject.getLibraryActivityUiImage()); + Long activityMaxMark = lamsCoreToolService.getActivityMaxPossibleMark(activity.getActivityId()); + if (activityMaxMark != null) { + activityJSON.put("maxMark", activityMaxMark); } - activityJSON.put("isGrouping", activityObject.isGroupingActivity()); + if (activity.getDuration() != null) { + activityJSON.put("duration", DateUtil.convertTimeToString(activity.getDuration())); + } + activityJSON.put("type", type); + activityJSON.put("isGrouping", actType.contains("grouping")); + if (activity.getChildActivities() != null) { for (ActivityURL childActivity : activity.getChildActivities()) { activityJSON.withArray("childActivities") Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/util/ActivityMapping.java =================================================================== diff -u -rbe74862925361d836bef1df4c5959105c9695a87 -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/util/ActivityMapping.java (.../ActivityMapping.java) (revision be74862925361d836bef1df4c5959105c9695a87) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/util/ActivityMapping.java (.../ActivityMapping.java) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -27,15 +27,14 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; -import javax.servlet.http.HttpServletRequest; - -import org.lamsfoundation.lams.learning.service.ILearnerFullService; +import org.apache.commons.lang.StringUtils; import org.lamsfoundation.lams.learning.service.LearnerServiceException; import org.lamsfoundation.lams.learning.web.controller.DisplayActivityController; import org.lamsfoundation.lams.learningdesign.Activity; import org.lamsfoundation.lams.learningdesign.dto.ActivityURL; import org.lamsfoundation.lams.lesson.LearnerProgress; import org.lamsfoundation.lams.lesson.Lesson; +import org.lamsfoundation.lams.lesson.util.LessonUtil; import org.lamsfoundation.lams.tool.exception.LamsToolServiceException; import org.lamsfoundation.lams.tool.service.ILamsCoreToolService; import org.lamsfoundation.lams.usermanagement.User; @@ -191,7 +190,15 @@ activityURL.setStatus(status); if (status == LearnerProgress.ACTIVITY_COMPLETED) { activityURL.setComplete(true); + + Long duration = LessonUtil.getActivityDuration(learnerProgress, activity); + activityURL.setDuration(duration); } + + if (StringUtils.isNotBlank(activity.getLibraryActivityUiImage())) { + activityURL.setIconURL(activity.getLibraryActivityUiImage()); + } + activityURL.setFloating(isFloating); activityURL.setDefaultURL(defaultURL); return activityURL; Index: lams_monitoring/web/css/components-monitoring.css =================================================================== diff -u -r6582c67f62fe86aeb15f5b7e21b54a82952ec3d3 -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_monitoring/web/css/components-monitoring.css (.../components-monitoring.css) (revision 6582c67f62fe86aeb15f5b7e21b54a82952ec3d3) +++ lams_monitoring/web/css/components-monitoring.css (.../components-monitoring.css) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -1206,11 +1206,6 @@ border-radius: 50%; } - -.learners-accordion-item-template { - display: none; -} - #learners-accordion .no-progress { display: none; text-align: center; @@ -1245,5 +1240,5 @@ } #learners-accordion .vertical-timeline:before { - bottom: 30px; + bottom: 90px; } Index: lams_monitoring/web/includes/javascript/monitorLesson5.js =================================================================== diff -u -r6582c67f62fe86aeb15f5b7e21b54a82952ec3d3 -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_monitoring/web/includes/javascript/monitorLesson5.js (.../monitorLesson5.js) (revision 6582c67f62fe86aeb15f5b7e21b54a82952ec3d3) +++ lams_monitoring/web/includes/javascript/monitorLesson5.js (.../monitorLesson5.js) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -2365,7 +2365,8 @@ */ function updateLearnersTab(){ let learnersAccordion = $('#learners-accordion').empty(), - itemTemplate = $('.learners-accordion-item-template').clone().removeClass('learners-accordion-item-template'); + itemTemplate = $('.learners-accordion-item-template').clone().removeClass('learners-accordion-item-template d-none'), + activityEntryTemplate = $('.learners-timeline-entry-template').clone().removeClass('learners-timeline-entry-template d-none'); $.ajax({ 'url' : LAMS_URL + 'monitoring/monitoring/getLearnerProgressPage.do', @@ -2416,18 +2417,19 @@ $(response.activities).each(function(){ let activity = this, - entry = $('
').addClass('timeline-entry').appendTo(timeline), - innerEntry = $('
').addClass('timeline-entry-inner').appendTo(entry), - icon = $('
').addClass('timeline-icon').appendTo(innerEntry), - content = $('
').addClass('timeline-label').appendTo(innerEntry), - title = $('

').addClass('timeline-title').text(activity.name).appendTo(content); + entry = activityEntryTemplate.clone().appendTo(timeline), + icon = $('.timeline-icon', entry), + iconURL = null, + durationCell = $('.timeline-activity-duration', entry), + markCell = $('.timeline-activity-mark', entry); + $('.timeline-title', entry).text(activity.name); + switch(activity.status){ - case 0: icon.addClass('bg-primary');break; - case 1: icon.addClass('bg-success');break; + case 0: icon.addClass('border-primary activity-current');break; + case 1: icon.addClass('border-success activity-complete');break; } - - let iconURL = null; + if (activity.iconURL) { iconURL = activity.iconURL; } else if (activity.type === 'g') { @@ -2437,10 +2439,22 @@ } else if (activity.isGrouping) { iconURL = 'images/svg/grouping.svg'; } - + if (iconURL) { $('').attr('src', LAMS_URL + iconURL).appendTo(icon); } + + if (typeof activity.mark !== 'undefined') { + markCell.text(activity.mark + (activity.maxMark ? ' / ' + activity.maxMark : '')); + } else { + markCell.closest('tr').remove(); + } + + if (activity.duration) { + durationCell.text(activity.duration); + } else { + durationCell.closest('tr').remove(); + } }); timelineContainer.show(); Index: lams_monitoring/web/monitor-learners-tab.jsp =================================================================== diff -u -rd7075108a6a77341ebefaa6dfdb8ce46f9d87c4a -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_monitoring/web/monitor-learners-tab.jsp (.../monitor-learners-tab.jsp) (revision d7075108a6a77341ebefaa6dfdb8ce46f9d87c4a) +++ lams_monitoring/web/monitor-learners-tab.jsp (.../monitor-learners-tab.jsp) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -5,7 +5,7 @@

-
+

@@ -36,6 +36,26 @@

+
+
+
+
+
+

+ + + + + + + + + +
Time taken
Mark
+
+
+
+ <%--
Index: lams_monitoring/web/monitor5.jsp =================================================================== diff -u -re3931b3fb440adbb62e0ab4112df71f620050066 -rbfa7dfb5557d54767b137652b34dd89c13fb1227 --- lams_monitoring/web/monitor5.jsp (.../monitor5.jsp) (revision e3931b3fb440adbb62e0ab4112df71f620050066) +++ lams_monitoring/web/monitor5.jsp (.../monitor5.jsp) (revision bfa7dfb5557d54767b137652b34dd89c13fb1227) @@ -16,7 +16,7 @@ - + @@ -26,12 +26,13 @@ - - + + - - + + +