diff --git a/src/main/java/org/olat/course/nodes/gta/ui/EditMultipleDueDatesController.java b/src/main/java/org/olat/course/nodes/gta/ui/EditMultipleDueDatesController.java new file mode 100644 index 0000000000000000000000000000000000000000..d9844a89be6fcd9f0d4833d0344ec09da5067725 --- /dev/null +++ b/src/main/java/org/olat/course/nodes/gta/ui/EditMultipleDueDatesController.java @@ -0,0 +1,134 @@ +/** + * <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.course.nodes.gta.ui; + +import java.util.List; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.DateChooser; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.Formatter; +import org.olat.course.nodes.GTACourseNode; +import org.olat.course.nodes.gta.GTAManager; +import org.olat.course.nodes.gta.Task; +import org.olat.course.nodes.gta.TaskDueDate; +import org.olat.course.nodes.gta.model.DueDate; +import org.olat.modules.ModuleConfiguration; +import org.olat.repository.RepositoryEntry; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 26.02.2018<br> + * @author Stephan Clemenz, clemenz@vcrp.de + * + */ +public class EditMultipleDueDatesController extends FormBasicController { + + private DateChooser assignmentDueDateEl, submissionDueDateEl, revisionDueDateEl, solutionDueDateEl; + + private List<Task> tasks; + private GTACourseNode gtaNode; + private final Formatter formatter; + private final RepositoryEntry courseEntry; + + @Autowired + private GTAManager gtaManager; + + public EditMultipleDueDatesController(UserRequest ureq, WindowControl wControl, List<Task> tasks, + GTACourseNode gtaNode, RepositoryEntry courseEntry) { + super(ureq, wControl); + this.tasks = tasks; + this.gtaNode = gtaNode; + this.courseEntry = courseEntry; + formatter = Formatter.getInstance(getLocale()); + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + ModuleConfiguration config = gtaNode.getModuleConfiguration(); + + assignmentDueDateEl = uifactory.addDateChooser("assignment.duedate", null, formLayout); + assignmentDueDateEl.setDateChooserTimeEnabled(true); + DueDate standardAssignmentDueDate = gtaManager.getAssignmentDueDate(null, null, null, gtaNode, courseEntry, false); + setDueDateExplanation(assignmentDueDateEl, standardAssignmentDueDate); + assignmentDueDateEl.setVisible(config.getBooleanSafe(GTACourseNode.GTASK_ASSIGNMENT)); + + submissionDueDateEl = uifactory.addDateChooser("submission.duedate", null, formLayout); + submissionDueDateEl.setDateChooserTimeEnabled(true); + DueDate standardSubmissionDueDate = gtaManager.getSubmissionDueDate(null, null, null, gtaNode, courseEntry, false); + setDueDateExplanation(submissionDueDateEl, standardSubmissionDueDate); + submissionDueDateEl.setVisible(config.getBooleanSafe(GTACourseNode.GTASK_SUBMIT)); + + revisionDueDateEl = uifactory.addDateChooser("revisions.duedate", null, formLayout); + revisionDueDateEl.setDateChooserTimeEnabled(true); + revisionDueDateEl.setVisible(config.getBooleanSafe(GTACourseNode.GTASK_REVISION_PERIOD)); + + solutionDueDateEl = uifactory.addDateChooser("solution.duedate", null, formLayout); + solutionDueDateEl.setDateChooserTimeEnabled(true); + DueDate standardSolutionDueDate = gtaManager.getSolutionDueDate(null, null, null, gtaNode, courseEntry, false); + setDueDateExplanation(solutionDueDateEl, standardSolutionDueDate); + solutionDueDateEl.setVisible(config.getBooleanSafe(GTACourseNode.GTASK_SAMPLE_SOLUTION)); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsCont); + uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl()); + uifactory.addFormSubmitButton("save", buttonsCont); + } + + private void setDueDateExplanation(DateChooser dateEl, DueDate standardDueDate) { + if(standardDueDate != null) { + if(standardDueDate.getDueDate() != null) { + dateEl.setExampleKey("duedate.standard", new String[] { formatter.formatDateAndTime(standardDueDate.getDueDate()) }); + } else if(standardDueDate.getMessageKey() != null) { + dateEl.setExampleKey(standardDueDate.getMessageKey(), new String[] { standardDueDate.getMessageArg() }); + } + } + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void formOK(UserRequest ureq) { + for (Task task : tasks) { + TaskDueDate dueDates = gtaManager.getDueDatesTask(task); + dueDates.setAssignmentDueDate(assignmentDueDateEl.getDate()); + dueDates.setSubmissionDueDate(submissionDueDateEl.getDate()); + dueDates.setRevisionsDueDate(revisionDueDateEl.getDate()); + dueDates.setSolutionDueDate(solutionDueDateEl.getDate()); + dueDates = gtaManager.updateTaskDueDate(dueDates); + } + fireEvent(ureq, Event.DONE_EVENT); + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedParticipantListController.java b/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedParticipantListController.java index fce9b564001d0ec1124cefc53675df10906cb31b..f1a6a5e0467639a12bb300b07b53e7c8d15b4c1d 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedParticipantListController.java +++ b/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedParticipantListController.java @@ -106,6 +106,7 @@ public class GTACoachedParticipantListController extends GTACoachedListControlle private CloseableModalController cmc; private EditDueDatesController editDueDatesCtrl; + private EditMultipleDueDatesController editMultipleDueDatesCtrl; @Autowired private GTAManager gtaManager; @@ -122,6 +123,8 @@ public class GTACoachedParticipantListController extends GTACoachedListControlle @Autowired private AssessmentService assessmentService; + private FormLink extendButton; + public GTACoachedParticipantListController(UserRequest ureq, WindowControl wControl, UserCourseEnvironment userCourseEnv, GTACourseNode gtaNode, boolean markedOnly) { super(ureq, wControl, userCourseEnv.getCourseEnvironment(), gtaNode); @@ -134,12 +137,8 @@ public class GTACoachedParticipantListController extends GTACoachedListControlle this.markedOnly = markedOnly; assessableIdentities = new ArrayList<>(); - collectIdentities(new Consumer<Identity>() { - @Override - public void accept(Identity participant) { - assessableIdentities.add(new UserPropertiesRow(participant, userPropertyHandlers, getLocale())); - } - }); + collectIdentities((participant) -> + assessableIdentities.add(new UserPropertiesRow(participant, userPropertyHandlers, getLocale()))); initForm(ureq); updateModel(ureq); @@ -253,6 +252,10 @@ public class GTACoachedParticipantListController extends GTACoachedListControlle tableEl = uifactory.addTableElement(getWindowControl(), "entries", tableModel, 10, false, getTranslator(), formLayout); tableEl.setShowAllRowsEnabled(true); tableEl.setAndLoadPersistedPreferences(ureq, "gta-coached-participants-" + markedOnly); + if(gtaManager.isDueDateEnabled(gtaNode) && !gtaNode.getModuleConfiguration().getBooleanSafe(GTACourseNode.GTASK_RELATIVE_DATES)) { + tableEl.setMultiSelect(true); + extendButton = uifactory.addFormLink("extend.list", "duedates", "duedates", formLayout, Link.BUTTON); + } } protected void updateModel(UserRequest ureq) { @@ -336,6 +339,12 @@ public class GTACoachedParticipantListController extends GTACoachedListControlle } cmc.deactivate(); cleanUp(); + } else if(editMultipleDueDatesCtrl == source) { + if(event == Event.DONE_EVENT) { + updateModel(ureq); + } + cmc.deactivate(); + cleanUp(); } else if(source == cmc) { cleanUp(); } @@ -343,8 +352,10 @@ public class GTACoachedParticipantListController extends GTACoachedListControlle } private void cleanUp() { + removeAsListenerAndDispose(editMultipleDueDatesCtrl); removeAsListenerAndDispose(editDueDatesCtrl); removeAsListenerAndDispose(cmc); + editMultipleDueDatesCtrl = null; editDueDatesCtrl = null; cmc = null; } @@ -362,6 +373,9 @@ public class GTACoachedParticipantListController extends GTACoachedListControlle fireEvent(ureq, new SelectIdentityEvent(row.getIdentity().getIdentityKey())); } } + } else if(extendButton == source) { + List<CoachedIdentityRow> rows = getSelectedRows(); + doEditMultipleDueDates(ureq, rows); } else if(source instanceof FormLink) { FormLink link = (FormLink)source; String cmd = link.getCmd(); @@ -380,6 +394,23 @@ public class GTACoachedParticipantListController extends GTACoachedListControlle // } + private List<CoachedIdentityRow> getSelectedRows() { + Set<Integer> selectedItems = tableEl.getMultiSelectedIndex(); + List<CoachedIdentityRow> rows = new ArrayList<>(selectedItems.size()); + if(!selectedItems.isEmpty()) { + for(Integer i:selectedItems) { + int index = i.intValue(); + if(index >= 0 && index < tableModel.getRowCount()) { + CoachedIdentityRow row = tableModel.getObject(index); + if(row != null) { + rows.add(row); + } + } + } + } + return rows; + } + private void doEditDueDate(UserRequest ureq, CoachedIdentityRow row) { if(editDueDatesCtrl != null) return; @@ -404,6 +435,34 @@ public class GTACoachedParticipantListController extends GTACoachedListControlle cmc.activate(); } + private void doEditMultipleDueDates(UserRequest ureq, List<CoachedIdentityRow> rows) { + if(editMultipleDueDatesCtrl != null) return; + + if(rows.isEmpty()) { + showWarning("error.atleast.task"); + } else { + List<Task> tasks = new ArrayList<Task>(rows.size()); + RepositoryEntry entry = coachCourseEnv.getCourseEnvironment().getCourseGroupManager().getCourseEntry(); + for (CoachedIdentityRow row : rows) { + if(row.getTask() == null) { + TaskProcess firstStep = gtaManager.firstStep(gtaNode); + TaskList taskList = gtaManager.getTaskList(entry, gtaNode); + tasks.add(gtaManager.createAndPersistTask(null, taskList, firstStep, null, securityManager.loadIdentityByKey(row.getIdentity().getIdentityKey()), gtaNode)); + } else { + tasks.add(gtaManager.getTask(row.getTask())); + } + } + + editMultipleDueDatesCtrl = new EditMultipleDueDatesController(ureq, getWindowControl(), tasks, gtaNode, entry); + listenTo(editMultipleDueDatesCtrl); + + String title = translate("duedates.multiple.user"); + cmc = new CloseableModalController(getWindowControl(), "close", editMultipleDueDatesCtrl.getInitialComponent(), true, title, true); + listenTo(cmc); + cmc.activate(); + } + } + private boolean doToogleMark(UserRequest ureq, Long particiantKey) { RepositoryEntry entry = courseEnv.getCourseGroupManager().getCourseEntry(); Identity participant = securityManager.loadIdentityByKey(particiantKey); diff --git a/src/main/java/org/olat/course/nodes/gta/ui/_content/coach_list.html b/src/main/java/org/olat/course/nodes/gta/ui/_content/coach_list.html index c3fa1de1610b45ee422cc39b78e2778655ca2b77..777a209d9f0b6f0c01afc92729a30891cc1c82cc 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/_content/coach_list.html +++ b/src/main/java/org/olat/course/nodes/gta/ui/_content/coach_list.html @@ -1,4 +1,9 @@ $r.render("entries") +#if($r.visible("extend.list")) +<div class="o_button_group"> + $r.render("extend.list") +</div> +#end <div class="clearfix">$r.contextHelpWithWrapper("Assessment#_task_coachview") <ul class="list-unstyled small"> <li><i class="o_icon o_icon-fw o_icon_info"> </i>: $r.translate("process.action.explanation")</li> diff --git a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_de.properties index a2e0120dc9ef48abc55fc3840d550982480eed19..82151156e9bd620362fc09f850586802769a76f0 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_de.properties @@ -83,12 +83,14 @@ download.task.infos={0} ({1} MB) duedate.standard=Standard Datum\: {0} duedates=Verl\u00E4ngern duedates.user=Verl\u00E4ngern f\u00FCr "{0}" +duedates.multiple.user=Verl\u00E4ngern f\u00FCr ausgew\u00E4hlte Benutzer edit.task=Aufgabe bearbeiten editor.revisions.title=R\u00FCckgabe Konfiguration editor.title=Abgabe Konfiguration embedded.editor=Abgabe mit OpenOLAT Texteditor enabled=eingeschaltet error.assignment.closed=Zuweisung ist geschlossen. +error.atleast.task=Sie m\u00FCssen mindestens eine Aufgabe w\u00E4hlen error.duplicate.coaching=Der Teilnehmer ist Teilnehmer von mehreren Gruppen f\u00FCr diese Aufgabe. error.duplicate.memberships=Die folgenden Teilnehmer sind Mitglieder von mehreren der eingebundenen Gruppen, und m\u00FCssen diese Aufgabe deshalb mehrfach bearbeiten\: {1} error.editor.atLeastOne=Sie m\u00FCssen mindestens einen Editortyp w\u00E4hlen. diff --git a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_en.properties index 611c06fcbda6f6e9e2d2b90401b379fe91eb6828..10e6dbe024145e3f9e80a27a4f73fec9657579b7 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_en.properties @@ -82,6 +82,7 @@ download.task=Download task download.task.infos={0} ({1} MB) duedate.standard=Standard date\: {0} duedates=Extend +duedates.multiple.user=Extend for the choosen users duedates.user=Extend for "{0}" edit.task=Edit task editor.revisions.title=Revision configuration @@ -89,6 +90,7 @@ editor.title=Submission configuration embedded.editor=Submit with OpenOLAT text editor enabled=enabled error.assignment.closed=Assignment is closed +error.atleast.task=You need to choose at least one task. error.duplicate.coaching=This user is a member of multiple groups in this task. error.duplicate.memberships=The following users are members of multiple groups, and are therefore required to hand in this assignment multiple times\: {1} error.editor.atLeastOne=You must choose at least one kind of editor.