/** * <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.reminder.ui; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.List; 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.FormLink; import org.olat.core.gui.components.form.flexible.elements.RichTextElement; import org.olat.core.gui.components.form.flexible.elements.SingleSelection; import org.olat.core.gui.components.form.flexible.elements.TextElement; 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.link.Link; 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.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.modules.reminder.Reminder; import org.olat.modules.reminder.ReminderModule; import org.olat.modules.reminder.ReminderRule; import org.olat.modules.reminder.ReminderService; import org.olat.modules.reminder.RuleEditorFragment; import org.olat.modules.reminder.RuleSPI; import org.olat.modules.reminder.model.ReminderRules; import org.olat.modules.reminder.model.SendTime; import org.olat.modules.reminder.rule.DateRuleSPI; import org.olat.modules.reminder.ui.ReminderAdminController; import org.olat.repository.RepositoryEntry; import org.springframework.beans.factory.annotation.Autowired; /** * * Initial date: 02.04.2015<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ public class CourseReminderEditController extends FormBasicController { private final String[] typeKeys; private final String[] typeValues; private RichTextElement emailEl; private TextElement descriptionEl; private FormLayoutContainer rulesCont; private final List<RuleElement> ruleEls = new ArrayList<>(); private Reminder reminder; private final RepositoryEntry entry; private int counter = 0; @Autowired private ReminderService reminderManager; @Autowired private ReminderModule reminderModule; public CourseReminderEditController(UserRequest ureq, WindowControl wControl, Reminder reminder) { super(ureq, wControl, LAYOUT_BAREBONE); setTranslator(Util.createPackageTranslator(ReminderAdminController.class, getLocale(), getTranslator())); this.reminder = reminder; this.entry = reminder.getEntry(); List<RuleSPI> orderedRuleSpies = new ArrayList<>(reminderModule.getRuleSPIList()); Collections.sort(orderedRuleSpies, new RuleSpiComparator()); typeKeys = new String[orderedRuleSpies.size()]; typeValues = new String[orderedRuleSpies.size()]; int count = 0; for(RuleSPI ruleSpy: orderedRuleSpies) { typeKeys[count] = ruleSpy.getClass().getSimpleName(); typeValues[count++] = translate(ruleSpy.getLabelI18nKey()); } initForm(ureq); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { FormLayoutContainer generalCont = FormLayoutContainer.createVerticalFormLayout("general", getTranslator()); generalCont.setRootForm(mainForm); generalCont.setFormContextHelp("Course Reminders"); formLayout.add(generalCont); String key = reminder.getKey() == null ? "" : reminder.getKey().toString(); uifactory.addStaticTextElement("reminder.id", key, generalCont); String desc = reminder.getDescription(); descriptionEl = uifactory.addTextElement("reminder.description", "reminder.description", 128, desc, generalCont); descriptionEl.setElementCssClass("o_sel_course_reminder_desc"); String sendTime = getSendTimeDescription(); uifactory.addStaticTextElement("send.time.description.label", sendTime, generalCont); //rules String rulePage = velocity_root + "/edit_rules.html"; rulesCont = FormLayoutContainer.createCustomFormLayout("rules", getTranslator(), rulePage); rulesCont.setRootForm(mainForm); formLayout.add(rulesCont); rulesCont.contextPut("rules", ruleEls); String configuration = reminder.getConfiguration(); if(StringHelper.containsNonWhitespace(configuration)) { ReminderRules rules = reminderManager.toRules(configuration); if(rules.getRules() != null) { for(ReminderRule rule: rules.getRules()) { if(rule != null) { RuleSPI ruleSpy = reminderModule.getRuleSPIByType(rule.getType()); RuleElement ruleEl = initRuleForm(ureq, ruleSpy, rule); ruleEls.add(ruleEl); } } } } if(ruleEls.isEmpty()) { doInitDefaultRule(ureq); } //email content FormLayoutContainer contentCont = FormLayoutContainer.createVerticalFormLayout("contents", getTranslator()); contentCont.setRootForm(mainForm); formLayout.add(contentCont); String emailContent = reminder == null ? null : reminder.getEmailBody(); if(!StringHelper.containsNonWhitespace(emailContent)) { emailContent = translate("reminder.def.body"); } emailEl = uifactory.addRichTextElementForStringDataMinimalistic("email.content", "email.content", emailContent, 10, 60, contentCont, getWindowControl()); String buttonPage = velocity_root + "/edit_rules_buttons.html"; FormLayoutContainer buttonLayout = FormLayoutContainer.createCustomFormLayout("buttons", getTranslator(), buttonPage); buttonLayout.setRootForm(mainForm); formLayout.add(buttonLayout); uifactory.addFormSubmitButton("save", buttonLayout); uifactory.addFormCancelButton("cancel", buttonLayout, ureq, getWindowControl()); } protected String getSendTimeDescription() { String interval = reminderModule.getInterval(); String desc = translate("interval." + interval); String time; SendTime parsedTime = SendTime.parse(reminderModule.getDefaultSendTime()); if(parsedTime.isValid()) { int hour = parsedTime.getHour(); int minute = parsedTime.getMinute(); Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, hour); cal.set(Calendar.MINUTE, minute); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); time = Formatter.getInstance(getLocale()).formatTimeShort(cal.getTime()); } else { time = "ERROR"; } String descText = translate("send.time.description", new String[] { desc, time} ); String infoText = "<br /><em class='text-muted'>" + translate("send.time.info") + "</em>"; return descText + infoText; } protected RuleElement initRuleForm(UserRequest ureq, RuleSPI ruleSpi, ReminderRule rule) { String id = Integer.toString(counter++); String type = ruleSpi.getClass().getSimpleName(); SingleSelection typeEl = uifactory.addDropdownSingleselect("rule.type.".concat(id), null, rulesCont, typeKeys, typeValues, null); typeEl.addActionListener(FormEvent.ONCHANGE); for(String typeKey : typeKeys) { if(type.equals(typeKey)) { typeEl.select(typeKey, true); } } FormLink addRuleButton = uifactory.addFormLink("add.rule.".concat(id), "add", "add.rule", null, rulesCont, Link.BUTTON); addRuleButton.setIconLeftCSS("o_icon o_icon-fw o_icon_add"); addRuleButton.setElementCssClass("o_sel_course_add_rule"); FormLink deleteRuleButton = uifactory.addFormLink("delete.rule.".concat(id), "delete", "delete.rule", null, rulesCont, Link.BUTTON); deleteRuleButton.setIconLeftCSS("o_icon o_icon-fw o_icon_delete_item"); deleteRuleButton.setElementCssClass("o_sel_course_delete_rule"); RuleEditorFragment editor = ruleSpi.getEditorFragment(rule, entry); FormItem customItem = editor.initForm(rulesCont, this, ureq); RuleElement ruleEl = new RuleElement(typeEl, addRuleButton, deleteRuleButton, editor, customItem); typeEl.setUserObject(ruleEl); addRuleButton.setUserObject(ruleEl); deleteRuleButton.setUserObject(ruleEl); return ruleEl; } @Override protected void doDispose() { // } @Override protected boolean validateFormLogic(UserRequest ureq) { boolean allOk = true; descriptionEl.clearError(); if(!StringHelper.containsNonWhitespace(descriptionEl.getValue())) { descriptionEl.setErrorKey("form.mandatory.hover", null); allOk &= false; } emailEl.clearError(); if(!StringHelper.containsNonWhitespace(emailEl.getValue())) { emailEl.setErrorKey("form.mandatory.hover", null); allOk &= false; } for(RuleElement ruleEl:ruleEls) { allOk &= ruleEl.getEditor().validateFormLogic(ureq); } return allOk & super.validateFormLogic(ureq); } @Override protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { if(source instanceof SingleSelection) { RuleElement panelToUpdate = null; for(RuleElement ruleEl:ruleEls) { if(source == ruleEl.getTypeEl()) { panelToUpdate = ruleEl; } } if(panelToUpdate != null) { SingleSelection typeEl = (SingleSelection)source; RuleSPI type = reminderModule.getRuleSPIByType(typeEl.getSelectedKey()); doUpdateRuleForm(ureq, panelToUpdate, type); } } else if(source instanceof FormLink) { FormLink button = (FormLink)source; String cmd = button.getCmd(); if("add".equals(cmd)) { doAddRule(ureq, (RuleElement)button.getUserObject()); } else if("delete".equals(cmd)) { doDeleteRule(ureq, (RuleElement)button.getUserObject()); } } super.formInnerEvent(ureq, source, event); } private void doUpdateRuleForm(UserRequest ureq, RuleElement panelToUpdate, RuleSPI ruleSpi) { //remove old editor rulesCont.remove(panelToUpdate.getCustomItem()); //add new one RuleEditorFragment editor = ruleSpi.getEditorFragment(null, entry); FormItem customItem = editor.initForm(rulesCont, this, ureq); panelToUpdate.setCustomItem(customItem, editor); rulesCont.setDirty(true); } private void doAddRule(UserRequest ureq, RuleElement ruleElement) { int index = ruleEls.indexOf(ruleElement) + 1; RuleSPI ruleSpi = reminderModule.getRuleSPIByType(DateRuleSPI.class.getSimpleName()); RuleElement ruleEl = initRuleForm(ureq, ruleSpi, null); if(index >= 0 && index < ruleEls.size()) { ruleEls.add(index, ruleEl); } else { ruleEls.add(ruleEl); } } private void doDeleteRule(UserRequest ureq, RuleElement ruleElement) { rulesCont.remove(ruleElement.getAddRuleButton()); rulesCont.remove(ruleElement.getDeleteRuleButton()); rulesCont.remove(ruleElement.getTypeEl()); rulesCont.remove(ruleElement.getCustomItem()); if(ruleEls.remove(ruleElement)) { rulesCont.setDirty(true); } if(ruleEls.isEmpty()) { doInitDefaultRule(ureq); } } private void doInitDefaultRule(UserRequest ureq) { RuleSPI ruleSpi = reminderModule.getRuleSPIByType(DateRuleSPI.class.getSimpleName()); RuleElement ruleEl = initRuleForm(ureq, ruleSpi, null); ruleEls.add(ruleEl); } @Override protected void formOK(UserRequest ureq) { String description = descriptionEl.getValue(); reminder.setDescription(description); ReminderRules rules = new ReminderRules(); for(RuleElement ruleEl:ruleEls) { ReminderRule rule = ruleEl.getEditor().getConfiguration(); if(rule != null) { rules.getRules().add(rule); } } String configuration = reminderManager.toXML(rules); reminder.setConfiguration(configuration); String emailBody = emailEl.getValue(); reminder.setEmailBody(emailBody); reminder = reminderManager.save(reminder); fireEvent(ureq, Event.DONE_EVENT); } @Override protected void formCancelled(UserRequest ureq) { fireEvent(ureq, Event.CANCELLED_EVENT); } private static class RuleSpiComparator implements Comparator<RuleSPI> { @Override public int compare(RuleSPI r1, RuleSPI r2) { String c1 = r1.getCategory(); String c2 = r2.getCategory(); int c = c1.compareTo(c2); if(c == 0) { String n1 = r1.getLabelI18nKey(); String n2 = r2.getLabelI18nKey(); c = n1.compareTo(n2); } return c; } } public static class RuleElement { private SingleSelection typeEl; private FormLink addRuleButton; private FormLink deleteRuleButton; private FormItem customItem; private RuleEditorFragment editor; public RuleElement(SingleSelection typeEl, FormLink addRuleButton, FormLink deleteRuleButton, RuleEditorFragment editor, FormItem customItem) { this.typeEl = typeEl; this.editor = editor; this.addRuleButton = addRuleButton; this.deleteRuleButton = deleteRuleButton; this.customItem = customItem; } public SingleSelection getTypeEl() { return typeEl; } public RuleEditorFragment getEditor() { return editor; } public FormLink getAddRuleButton() { return addRuleButton; } public FormLink getDeleteRuleButton() { return deleteRuleButton; } public String getTypeComponentName() { return typeEl.getName(); } public String getAddButtonName() { return addRuleButton.getComponent().getComponentName(); } public String getDeleteButtonName() { return deleteRuleButton.getComponent().getComponentName(); } public FormItem getCustomItem() { return customItem; } public String getCustomItemName() { return customItem.getName(); } public void setCustomItem(FormItem customItem, RuleEditorFragment editor) { this.editor = editor; this.customItem = customItem; } } }