Skip to content
Snippets Groups Projects
Commit 343739e9 authored by uhensler's avatar uhensler
Browse files

OO-4481: Bulk edit of general course element configurations

parent 97e9903c
No related branches found
No related tags found
No related merge requests found
......@@ -7,6 +7,7 @@ alternative.choose=Alternativen Kursbaustein w\u00E4hlen und konvertieren
alternative.choose.description=W\u00E4hlen Sie aus der Liste der m\u00F6glichen alternativen Kursbausteine mit \u00E4hnlicher Funktionalit\u00E4t einen aus um diesen deaktivierten Kursbaustein zu konvertieren. Es werden der Titel und die Beschreibung sowie die Zugangsregeln und alle Kinderelemente \u00FCbernommen.
apply=OK
assessment=Wissens\u00FCberpr\u00FCfung
bulk.general=$\:pane.tab.general
checkall=Alle ausw\u00E4hlen
checklist.wizard=Checklisten
......@@ -339,6 +340,7 @@ cif.access.users_guests=$org.olat.repository\:cif.access.users_guests
cif.access.publisc.desc=Publizieren Sie manuell um diese Zugangskonfiguration zu \u00E4ndern.
collaboration=Kommunikation und Kollaboration
command.admin.header=Sammelfunktion
command.bulk=Kunfiguration \u00E4ndern
command.closeeditor=Editor schliessen
command.copynode=Kopieren
command.coursepreview=Kursvorschau
......@@ -369,6 +371,7 @@ deletenode.no=Abbrechen
deletenode.success=Der Kursbaustein wurde als gel\u00F6scht markiert. Er wird permanent gel\u00F6scht, sobald Sie diese \u00C4nderung publiziert haben.
deletenode.yes=Kursbaustein inkl. alle untergeordneten Kursbausteine l\u00F6schen
disabled=Deaktiviert
error.select.one.course.node=Sie m\u00FCssen mindestens ein Kurselement ausw\u00E4hlen.
fix.it=Gehe zu
form.legende.mandatory=Obligatorische Angaben
form.noAccessExplanation=Text
......
......@@ -7,6 +7,7 @@ alternative.choose=Select an alternative course element and convert
alternative.choose.description=Select from the list of alternative course elements that offer similar functionality to convert this deactivated course element. The title, description, access rules and all child element will be copied to the converted element.
apply=OK
assessment=Assessment
bulk.general=$\:pane.tab.general
checkall=Select all
checklist.wizard=Checklist set
......@@ -339,6 +340,7 @@ cif.access.users=$org.olat.repository\:cif.access.users
cif.access.users_guests=$org.olat.repository\:cif.access.users_guests
collaboration=Communication and collaboration
command.admin.header=Collecting function
command.bulk=Change configuration
command.closeeditor=Close editor
command.copynode=Copy
command.coursepreview=Course preview
......@@ -369,6 +371,7 @@ deletenode.no=Cancel
deletenode.success=This course element was marked as deleted. It will be deleted permanently as soon as you have published this modification.
deletenode.yes=Delete course element incl. all its sub-elements
disabled=Disabled
error.select.one.course.node=You must select at least one course element.
fix.it=Go to
form.legende.mandatory=Mandatory details
form.noAccessExplanation=Text
......
/**
* <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.editor.overview;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.FormItem;
import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
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.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.Util;
import org.olat.course.editor.EditorMainController;
import org.olat.course.nodes.CourseNode;
/**
*
* Initial date: 21 Jan 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class BulkChangeController extends FormBasicController {
private static final String[] EMPTY_VALUES = new String[]{ "" };
private static final String[] displayOptionsKeys = new String[]{
CourseNode.DISPLAY_OPTS_SHORT_TITLE_DESCRIPTION_CONTENT,
CourseNode.DISPLAY_OPTS_TITLE_DESCRIPTION_CONTENT,
CourseNode.DISPLAY_OPTS_SHORT_TITLE_CONTENT,
CourseNode.DISPLAY_OPTS_TITLE_CONTENT,
CourseNode.DISPLAY_OPTS_CONTENT};
private SingleSelection displayEl;
private Map<MultipleSelectionElement, FormLayoutContainer> checkboxContainer = new HashMap<>();
private final List<MultipleSelectionElement> checkboxSwitch = new ArrayList<>();
private final List<CourseNode> courseNodes;
public BulkChangeController(UserRequest ureq, WindowControl wControl, List<CourseNode> courseNodes) {
super(ureq, wControl, LAYOUT_VERTICAL);
setTranslator(Util.createPackageTranslator(EditorMainController.class, getLocale(), getTranslator()));
this.courseNodes = courseNodes;
initForm(ureq);
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
initGeneralForm(formLayout);
FormLayoutContainer buttonsWrapperCont = FormLayoutContainer.createDefaultFormLayout("global", getTranslator());
buttonsWrapperCont.setRootForm(mainForm);
formLayout.add("buttonsWrapper", buttonsWrapperCont);
FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
buttonsCont.setRootForm(mainForm);
buttonsWrapperCont.add(buttonsCont);
uifactory.addFormSubmitButton("ok", "ok", buttonsCont);
uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl());
}
private void initGeneralForm(FormItemContainer formLayout) {
FormLayoutContainer generalCont = FormLayoutContainer.createDefaultFormLayout("general", getTranslator());
generalCont.setRootForm(mainForm);
formLayout.add(generalCont);
String[] values = new String[]{
translate("nodeConfigForm.short_title_desc_content"),
translate("nodeConfigForm.title_desc_content"),
translate("nodeConfigForm.short_title_content"),
translate("nodeConfigForm.title_content"),
translate("nodeConfigForm.content_only")};
displayEl = uifactory.addDropdownSingleselect("nodeConfigForm.display_options", generalCont, displayOptionsKeys,
values, null);
decorate(displayEl, generalCont);
}
private FormItem decorate(FormItem item, FormLayoutContainer formLayout) {
String itemName = item.getName();
MultipleSelectionElement checkbox = uifactory.addCheckboxesHorizontal("cbx_" + itemName, itemName, formLayout,
new String[] { itemName }, EMPTY_VALUES);
checkbox.select(itemName, false);
checkbox.addActionListener(FormEvent.ONCLICK);
checkbox.setUserObject(item);
checkboxSwitch.add(checkbox);
item.setLabel(null, null);
item.setVisible(false);
item.setUserObject(checkbox);
checkboxContainer.put(checkbox, formLayout);
formLayout.moveBefore(checkbox, item);
return checkbox;
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if (checkboxSwitch.contains(source)) {
MultipleSelectionElement checkbox = (MultipleSelectionElement)source;
FormItem item = (FormItem)checkbox.getUserObject();
item.setVisible(checkbox.isAtLeastSelected(1));
checkboxContainer.get(checkbox).setDirty(true);
super.formInnerEvent(ureq, source, event);
}
}
@Override
protected void formOK(UserRequest ureq) {
for (CourseNode courseNode : courseNodes) {
formOKGeneral(courseNode);
}
// for(QuestionItemShort item : items) {
// QuestionItem fullItem = qpoolService.loadItemById(item.getKey());
// if(fullItem instanceof QuestionItemImpl) {
// QuestionItemImpl itemImpl = (QuestionItemImpl)fullItem;
// QuestionItemAuditLogBuilder builder = qpoolService.createAuditLogBuilder(getIdentity(),
// Action.UPDATE_QUESTION_ITEM_METADATA);
// builder.withBefore(itemImpl);
//
// formOKGeneral(itemImpl);
// formOKQuestion(itemImpl);
// formOKTechnical(itemImpl);
// formOKRights(itemImpl);
// QuestionItem merged = qpoolService.updateItem(itemImpl);
// builder.withAfter(itemImpl);
// qpoolService.persist(builder.create());
// updatedItems.add(merged);
// }
// }
fireEvent(ureq, Event.DONE_EVENT);
}
private void formOKGeneral(CourseNode courseNode) {
if(isEnabled(displayEl)) {
String displayOption = displayEl.getSelectedKey();
courseNode.setDisplayOption(displayOption);
}
}
private boolean isEnabled(FormItem item) {
if (item == null) return false;
return ((MultipleSelectionElement)item.getUserObject()).isAtLeastSelected(1);
}
@Override
protected void formCancelled(UserRequest ureq) {
fireEvent(ureq, Event.CANCELLED_EVENT);
}
@Override
protected void doDispose() {
//
}
}
......@@ -21,26 +21,36 @@ package org.olat.course.editor.overview;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
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;
import org.olat.core.gui.components.form.flexible.elements.FormLink;
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.FormLayoutContainer;
import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel;
import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer;
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.form.flexible.impl.elements.table.TreeNodeFlexiCellRenderer;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.tree.TreeNode;
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.gui.control.generic.closablewrapper.CloseableModalController;
import org.olat.core.util.Util;
import org.olat.core.util.nodes.INode;
import org.olat.course.ICourse;
import org.olat.course.assessment.IndentedNodeRenderer;
import org.olat.course.editor.EditorMainController;
import org.olat.course.editor.NodeEditController;
import org.olat.course.editor.overview.OverviewDataModel.OverviewCols;
import org.olat.course.learningpath.FullyAssessedTrigger;
import org.olat.course.learningpath.LearningPathConfigs;
......@@ -64,7 +74,11 @@ public class OverviewListController extends FormBasicController {
private FlexiTableElement tableEl;
private OverviewDataModel dataModel;
private FormLink bulkLink;
private CloseableModalController cmc;
private BulkChangeController bulkChangeCtrl;
private final ICourse course;
private final boolean learningPath;
......@@ -84,6 +98,7 @@ public class OverviewListController extends FormBasicController {
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
initTable(ureq, formLayout);
initButtons(formLayout);
}
private void initTable(UserRequest ureq, FormItemContainer formLayout) {
......@@ -114,6 +129,7 @@ public class OverviewListController extends FormBasicController {
tableEl = uifactory.addTableElement(getWindowControl(), "table", dataModel, 250, false, getTranslator(), formLayout);
tableEl.setAndLoadPersistedPreferences(ureq, "course-editor-overview");
tableEl.setEmtpyTableMessageKey("table.empty");
tableEl.setMultiSelect(true);
tableEl.setBordered(true);
loadModel();
......@@ -124,7 +140,7 @@ public class OverviewListController extends FormBasicController {
List<OverviewRow> rows = new ArrayList<>();
forgeRows(rows, rootNode, 0, null);
dataModel.setObjects(rows);
tableEl.reset(true, true, true);
tableEl.reset(true, false, true);
}
private void forgeRows(List<OverviewRow> rows, INode node, int recursionLevel, OverviewRow parent) {
......@@ -214,7 +230,68 @@ public class OverviewListController extends FormBasicController {
}
return null;
}
private void initButtons(FormItemContainer formLayout) {
FormLayoutContainer buttonCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
buttonCont.setElementCssClass("o_button_group");
buttonCont.setRootForm(mainForm);
formLayout.add("buttons", buttonCont);
bulkLink = uifactory.addFormLink("command.bulk", buttonCont, Link.BUTTON);
}
@Override
protected void event(UserRequest ureq, Controller source, Event event) {
if(source == bulkChangeCtrl) {
if (event == FormEvent.DONE_EVENT) {
fireEvent(ureq, NodeEditController.NODECONFIG_CHANGED_EVENT);
loadModel();
}
cmc.deactivate();
cleanUp();
} else if (source == cmc) {
cleanUp();
}
super.event(ureq, source, event);
}
private void cleanUp() {
removeAsListenerAndDispose(bulkChangeCtrl);
removeAsListenerAndDispose(cmc);
bulkChangeCtrl = null;
cmc = null;
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if (source == bulkLink) {
doBulk(ureq);
}
super.formInnerEvent(ureq, source, event);
}
private void doBulk(UserRequest ureq) {
Set<Integer> selectedIndex = tableEl.getMultiSelectedIndex();
if (selectedIndex.isEmpty()) {
showWarning("error.select.one.course.node");
return;
}
List<CourseNode> selectedCourseNodes = selectedIndex.stream()
.map(index -> dataModel.getObject(index.intValue()))
.map(OverviewRow::getCourseNode)
.collect(Collectors.toList());
removeAsListenerAndDispose(bulkChangeCtrl);
bulkChangeCtrl = new BulkChangeController(ureq, getWindowControl(), selectedCourseNodes);
listenTo(bulkChangeCtrl);
cmc = new CloseableModalController(getWindowControl(), translate("close"), bulkChangeCtrl.getInitialComponent(),
true, translate("command.bulk"));
cmc.activate();
listenTo(cmc);
}
@Override
protected void formOK(UserRequest ureq) {
//
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment