/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <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>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/
package org.olat.course.nodes.sp;
import org.olat.commons.file.filechooser.FileChooseCreateEditController;
import org.olat.commons.file.filechooser.LinkChooseCreateEditController;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.form.Form;
import org.olat.core.gui.components.panel.Panel;
import org.olat.core.gui.components.tabbedpane.TabbedPane;
import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.ControllerEventListener;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.tabbable.ActivateableTabbableDefaultController;
import org.olat.core.gui.formelements.StaticSingleSelectionElement;
import org.olat.core.gui.formelements.VisibilityDependsOnSelectionRule;
import org.olat.core.gui.translator.Translator;
import org.olat.core.util.StringHelper;
import org.olat.course.ICourse;
import org.olat.course.assessment.AssessmentHelper;
import org.olat.course.condition.Condition;
import org.olat.course.condition.ConditionEditController;
import org.olat.course.editor.NodeEditController;
import org.olat.course.groupsandrights.CourseGroupManager;
import org.olat.course.nodes.SPCourseNode;
import org.olat.course.run.userview.UserCourseEnvironment;
import org.olat.course.tree.CourseEditorTreeModel;
import org.olat.course.tree.CourseInternalLinkTreeModel;
import org.olat.modules.ModuleConfiguration;
/**
* Description:<BR/>
* Edit controller for single page course nodes
* <P/>
* Initial Date: Oct 12, 2004
*
* @author Felix Jost
* @author BPS (<a href="http://www.bps-system.de/">BPS Bildungsportal Sachsen GmbH</a>)
*/
public class SPEditController extends ActivateableTabbableDefaultController implements ControllerEventListener {
public static final String PANE_TAB_SPCONFIG = "pane.tab.spconfig";
private static final String PANE_TAB_ACCESSIBILITY = "pane.tab.accessibility";
/** configuration key for the filename */
public static final String CONFIG_KEY_FILE = "file";
/** configuration key: should relative links like ../otherfolder/my.css be allowed? **/
public static final String CONFIG_KEY_ALLOW_RELATIVE_LINKS = "allowRelativeLinks";
/** Configuration key: display content in iframe: Values: true, false **/
public static final String CONFIG_IFRAME = "iniframe";
/** Configuration key: Values (true,false) if the "SinglePage" is an entrance to a whole website, one can choose if a click in the menutree always shows the configured URL or if the last activated content is displayed.*/
public static final String CONFIG_KEY_STATEFUL ="statefulMicroWeb";
/** Configuration key: if the configured singlepage is in fact the startpage of a whole website it must be possible to navigate back to the start page, the name of this navigation element can be specified. Important for legacy content.*/
public static final String CONFIG_KEY_HOMELINK ="startPageActivationLinkName";
/***/
public static final String KEY_TRUE_WITHOUT_HOMELINK = "trueWithoutHomelink";
private static final String[] paneKeys = {PANE_TAB_SPCONFIG, PANE_TAB_ACCESSIBILITY};
// NLS support:
private static final String NLS_CONDITION_ACCESSIBILITY_TITLE = "condition.accessibility.title";
protected static final String[] ALLOWED_FILE_SUFFIXES_NO_IFRAME
= new String[] { "html", "htm" };
private ModuleConfiguration moduleConfiguration;
private VelocityContainer myContent;
private Panel fcPanel;
private SPCourseNode courseNode;
private Boolean allowRelativeLinks;
private ConditionEditController accessibilityCondContr;
private FileChooseCreateEditController fccecontr;
private TabbedPane myTabbedPane;
private IframeForm iframeForm;
/**
* Constructor for single page editor controller
* @param config The node module configuration
* @param ureq The user request
* @param wControl The window controller
* @param spCourseNode The current single page course node
* @param course
* @param euce
*/
public SPEditController(ModuleConfiguration config, UserRequest ureq,
WindowControl wControl, SPCourseNode spCourseNode, ICourse course, UserCourseEnvironment euce) {
super(ureq, wControl);
this.moduleConfiguration = config;
this.courseNode = spCourseNode;
myContent = this.createVelocityContainer("edit");
// whether to use iframes or not
boolean useIframe = moduleConfiguration.getBooleanSafe(CONFIG_IFRAME);
String statefulMicroWeb = (String)moduleConfiguration.get(CONFIG_KEY_STATEFUL);
iframeForm = new IframeForm("iframeform", getTranslator(), useIframe, statefulMicroWeb);
iframeForm.addSubmitKey("save");
iframeForm.addListener(this);
myContent.put("iframeForm", iframeForm);
String chosenFile = (String) config.get(CONFIG_KEY_FILE);
iframeForm.forceIframe(chosenFile);
allowRelativeLinks = moduleConfiguration.getBooleanEntry(CONFIG_KEY_ALLOW_RELATIVE_LINKS);
fccecontr = new LinkChooseCreateEditController(ureq, getWindowControl(), chosenFile, allowRelativeLinks, course.getCourseFolderContainer(), new CourseInternalLinkTreeModel(course.getEditorTreeModel()) );
this.listenTo(fccecontr);
fccecontr.setIframeEnabled(useIframe);
if (useIframe) {
fccecontr.setAllFileSuffixesAllowed(true);
} else {
// Without Iframe only HTML files can be rendered by SP
// Per default the FileChooseCreateEditController handle html, htm, xml, xhtml
fccecontr.setAllFileSuffixesAllowed(false);
fccecontr.setAllowedFileSuffixes(ALLOWED_FILE_SUFFIXES_NO_IFRAME);
}
fccecontr.setShowHomeLink(!statefulMicroWeb.equals(KEY_TRUE_WITHOUT_HOMELINK));
fcPanel = new Panel("filechoosecreateedit");
Component fcContent = fccecontr.getInitialComponent();
fcPanel.setContent(fcContent);
myContent.put(fcPanel.getComponentName(), fcPanel);
CourseGroupManager groupMgr = course.getCourseEnvironment().getCourseGroupManager();
CourseEditorTreeModel editorModel = course.getEditorTreeModel();
//Accessibility precondition
Condition accessCondition = courseNode.getPreConditionAccess();
accessibilityCondContr = new ConditionEditController(ureq, getWindowControl(), groupMgr, accessCondition,
"accessabilityConditionForm", AssessmentHelper.getAssessableNodes(editorModel, spCourseNode), euce);
this.listenTo(accessibilityCondContr);
}
/**
* @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
* org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
*/
public void event(UserRequest ureq, Component source, Event event) {
if (source == iframeForm) {
if (event == Form.EVNT_VALIDATION_OK) {
boolean useIframe = iframeForm.iframeE.getSelectedKey().equals(Boolean.TRUE.toString());
moduleConfiguration.setBooleanEntry(CONFIG_IFRAME, useIframe);
String statefulMicroWeb = iframeForm.statefulMicroWeb.getSelectedKey();
moduleConfiguration.set(CONFIG_KEY_STATEFUL, statefulMicroWeb);
// update preview behaviour of file choose controller
fccecontr.setIframeEnabled(useIframe);
fccecontr.setShowHomeLink(!statefulMicroWeb.equals(KEY_TRUE_WITHOUT_HOMELINK));
if (useIframe) {
fccecontr.setAllFileSuffixesAllowed(true);
} else {
fccecontr.setAllFileSuffixesAllowed(false);
String chosenFile = ((String) moduleConfiguration.get(CONFIG_KEY_FILE));
if (chosenFile != null) {
chosenFile = chosenFile.toUpperCase();
if (chosenFile.endsWith("HTML") || chosenFile.endsWith("HTM")) {
// Without Iframe only HTML files can be rendered by SP
// Per default the FileChooseCreateEditController handle html,
// htm, xml, xhtml
fccecontr.setAllowedFileSuffixes(new String[] { "html", "htm" });
} else {
// switch to no-iframe mode not allowed, wrong file type (xml)
this.showError("error.msg.can.not.switch.off.iframe");
moduleConfiguration.setBooleanEntry(CONFIG_IFRAME, true);
iframeForm.iframeE.select(Boolean.TRUE.toString(), true);
}
}//else if chosenFile is null just go ahead
}
fireEvent(ureq, NodeEditController.NODECONFIG_CHANGED_EVENT);
}
}
}
/**
* @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
*/
public void event(UserRequest urequest, Controller source, Event event) {
if (source == accessibilityCondContr) {
if (event == Event.CHANGED_EVENT) {
Condition cond = accessibilityCondContr.getCondition();
courseNode.setPreConditionAccess(cond);
fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
}
}
else if (source == fccecontr) {
if (event == FileChooseCreateEditController.FILE_CHANGED_EVENT) {
String chosenFile = fccecontr.getChosenFile();
if (chosenFile != null) {
moduleConfiguration.set(CONFIG_KEY_FILE, fccecontr.getChosenFile());
} else {
moduleConfiguration.remove(CONFIG_KEY_FILE);
}
fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
iframeForm.forceIframe(chosenFile);
} else if (event == FileChooseCreateEditController.FILE_CONTENT_CHANGED_EVENT) {
fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
} else if (event == FileChooseCreateEditController.ALLOW_RELATIVE_LINKS_CHANGED_EVENT) {
allowRelativeLinks = fccecontr.getAllowRelativeLinks();
courseNode.getModuleConfiguration().setBooleanEntry(CONFIG_KEY_ALLOW_RELATIVE_LINKS, allowRelativeLinks.booleanValue());
fireEvent(urequest, NodeEditController.NODECONFIG_CHANGED_EVENT);
}
}
}
/**
* @see org.olat.core.gui.control.generic.tabbable.TabbableController#addTabs(org.olat.core.gui.components.TabbedPane)
*/
public void addTabs(TabbedPane tabbedPane) {
myTabbedPane = tabbedPane;
tabbedPane.addTab(translate(PANE_TAB_ACCESSIBILITY), accessibilityCondContr.getWrappedDefaultAccessConditionVC(translate(NLS_CONDITION_ACCESSIBILITY_TITLE)));
tabbedPane.addTab(translate(PANE_TAB_SPCONFIG), myContent);
}
/**
*
* @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
*/
protected void doDispose() {
//child controllers registered with listenTo() get disposed in BasicController
}
public String[] getPaneKeys() {
return paneKeys;
}
public TabbedPane getTabbedPane() {
return myTabbedPane;
}
}
class IframeForm extends Form {
// NLS support:
private static final String NLS_DISPLAY_CONFIG_IFRAME_TRUE = "display.config.iframe.true";
private static final String NLS_DISPLAY_CONFIG_IFRAME_FALSE = "display.config.iframe.false";
private static final String NLS_DISPLAY_CONFIG_IFRAME = "display.config.iframe";
private static final String NLS_DISPLAY_CONFIG_STATEFUL_TRUE = "display.config.stateful.true";
private static final String NLS_DISPLAY_CONFIG_STATEFUL_FALSE = "display.config.stateful.false";
private static final String NLS_DISPLAY_CONFIG_STATEFUL_TRUEWITHOUT = "display.config.stateful.truewithout";
private static final String NLS_DISPLAY_CONFIG_STATEFUL = "display.config.stateful";
StaticSingleSelectionElement statefulMicroWeb;
StaticSingleSelectionElement iframeE;
IframeForm(String name, Translator translator, boolean initiallyChecked, String stateful) {
super(name, translator);
String[] iframeKeys = new String[] {
Boolean.TRUE.toString(),
Boolean.FALSE.toString() };
String[] iframeValues = new String[] {
translate(NLS_DISPLAY_CONFIG_IFRAME_TRUE),
translate(NLS_DISPLAY_CONFIG_IFRAME_FALSE) };
iframeE = new StaticSingleSelectionElement(NLS_DISPLAY_CONFIG_IFRAME, iframeKeys, iframeValues);
// in iFrame switch
if (initiallyChecked) {
iframeE.select(Boolean.TRUE.toString(), true);
} else {
iframeE.select(Boolean.FALSE.toString(), true);
}
addFormElement("iframe", iframeE);
// stateful switch
String[] statefulKeys = new String[] {
Boolean.TRUE.toString(),
Boolean.FALSE.toString(),
SPEditController.KEY_TRUE_WITHOUT_HOMELINK };
String[] statefulValues = new String[] {
translate(NLS_DISPLAY_CONFIG_STATEFUL_TRUE),
translate(NLS_DISPLAY_CONFIG_STATEFUL_FALSE),
translate(NLS_DISPLAY_CONFIG_STATEFUL_TRUEWITHOUT) };
statefulMicroWeb = new StaticSingleSelectionElement(NLS_DISPLAY_CONFIG_STATEFUL, statefulKeys, statefulValues);
statefulMicroWeb.select(stateful, true);
addFormElement("microWeb", statefulMicroWeb);
// enable statefulMicroWeb only if the page is not displayed in an iframe.
VisibilityDependsOnSelectionRule rule = new VisibilityDependsOnSelectionRule(iframeE, statefulMicroWeb, Boolean.FALSE.toString(), true, Boolean.FALSE.toString(), false);
addVisibilityDependsOnSelectionRule(rule);
}
public void forceIframe(String chosenFile) {
boolean forceIframe = true;
if(StringHelper.containsNonWhitespace(chosenFile)) {
for(int i=0; i<SPEditController.ALLOWED_FILE_SUFFIXES_NO_IFRAME.length; i++) {
if (chosenFile.endsWith("." + SPEditController.ALLOWED_FILE_SUFFIXES_NO_IFRAME[i]) ) {
forceIframe = false;
break;
}
}
} else {
forceIframe = false;
}
if(forceIframe) {
iframeE.select(Boolean.TRUE.toString(), true);
iframeE.setReadOnly(true);
} else if(iframeE.isReadOnly()) {
iframeE.setReadOnly(false);
}
}
public boolean validate() {
return true;
}
}