diff --git a/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java b/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java index 98a5c3d097cbd30574f5bce2841eac6753b1c8c5..091f4e1bb31716ee352389c5f000f881ec17cb9b 100644 --- a/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java +++ b/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java @@ -55,6 +55,7 @@ import org.olat.course.run.scoring.AssessmentEvaluation; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.ims.lti.LTIDisplayOptions; import org.olat.ims.lti.LTIManager; import org.olat.ims.lti.ui.LTIResultDetailsController; import org.olat.modules.ModuleConfiguration; @@ -71,7 +72,8 @@ public class BasicLTICourseNode extends AbstractAccessableCourseNode implements private static final long serialVersionUID = 2210572148308757127L; private static final String translatorPackage = Util.getPackageName(LTIEditController.class); private static final String TYPE = "lti"; - + + public static final int CURRENT_VERSION = 3; public static final String CONFIG_KEY_AUTHORROLE = "authorRole"; public static final String CONFIG_KEY_COACHROLE = "coachRole"; public static final String CONFIG_KEY_PARTICIPANTROLE = "participantRole"; @@ -79,6 +81,8 @@ public class BasicLTICourseNode extends AbstractAccessableCourseNode implements public static final String CONFIG_KEY_HAS_SCORE_FIELD = MSCourseNode.CONFIG_KEY_HAS_SCORE_FIELD; public static final String CONFIG_KEY_HAS_PASSED_FIELD = MSCourseNode.CONFIG_KEY_HAS_PASSED_FIELD; public static final String CONFIG_KEY_PASSED_CUT_VALUE = MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE; + public static final String CONFIG_SKIP_LAUNCH_PAGE = "skiplaunchpage"; + public static final String CONFIG_SKIP_ACCEPT_LAUNCH_PAGE = "skipacceptlaunchpage"; public static final String CONFIG_HEIGHT = "displayHeight"; public static final String CONFIG_WIDTH = "displayWidth"; public static final String CONFIG_HEIGHT_AUTO = DeliveryOptions.CONFIG_HEIGHT_AUTO; @@ -239,7 +243,8 @@ public class BasicLTICourseNode extends AbstractAccessableCourseNode implements if (isNewNode) { // use defaults for new course building blocks config.setBooleanEntry(NodeEditController.CONFIG_STARTPAGE, Boolean.FALSE.booleanValue()); - config.setConfigurationVersion(2); + config.setBooleanEntry(CONFIG_SKIP_LAUNCH_PAGE, Boolean.FALSE.booleanValue()); + config.setBooleanEntry(CONFIG_SKIP_ACCEPT_LAUNCH_PAGE, Boolean.FALSE.booleanValue()); } else { // clear old popup configuration config.remove(NodeEditController.CONFIG_INTEGRATION); @@ -248,10 +253,17 @@ public class BasicLTICourseNode extends AbstractAccessableCourseNode implements if (config.getConfigurationVersion() < 2) { // update new configuration options using default values for existing nodes config.setBooleanEntry(NodeEditController.CONFIG_STARTPAGE, Boolean.TRUE.booleanValue()); - config.setConfigurationVersion(2); } - // else node is up-to-date - nothing to do + if (config.getConfigurationVersion() < 3) { + if (BasicLTICourseNode.CONFIG_DISPLAY.equals(LTIDisplayOptions.window.name())) { + config.setBooleanEntry(CONFIG_SKIP_LAUNCH_PAGE, Boolean.FALSE.booleanValue()); + } else { + config.setBooleanEntry(CONFIG_SKIP_LAUNCH_PAGE, Boolean.TRUE.booleanValue()); + } + config.setBooleanEntry(CONFIG_SKIP_ACCEPT_LAUNCH_PAGE, Boolean.FALSE.booleanValue()); + } } + config.setConfigurationVersion(CURRENT_VERSION); } @Override diff --git a/src/main/java/org/olat/course/nodes/basiclti/LTIConfigForm.java b/src/main/java/org/olat/course/nodes/basiclti/LTIConfigForm.java index a89cdfe8f07e7c179ab66d2220b93d26a1afb0ff..16314d7226d4b9ea2ffdce76ac5901f1204e7880 100644 --- a/src/main/java/org/olat/course/nodes/basiclti/LTIConfigForm.java +++ b/src/main/java/org/olat/course/nodes/basiclti/LTIConfigForm.java @@ -59,11 +59,8 @@ import org.olat.user.UserManager; import org.olat.user.propertyhandlers.UserPropertyHandler; /** - * Description:<BR/> - * TODO: Class Description for LTConfigForm - * <P/> * -* @author guido + * @author guido * @author Charles Severance */ public class LTIConfigForm extends FormBasicController { @@ -78,10 +75,10 @@ public class LTIConfigForm extends FormBasicController { public static final String[] PROTOCOLS = new String[] {"http", "https"}; - public static final String CONFIG_KEY_DEBUG = "debug"; - public static final String CONFIG_KEY_CUSTOM = "custom"; - public static final String CONFIG_KEY_SENDNAME = "sendname"; - public static final String CONFIG_KEY_SENDEMAIL = "sendemail"; + public static final String CONFIG_KEY_DEBUG = "debug"; + public static final String CONFIG_KEY_CUSTOM = "custom"; + public static final String CONFIG_KEY_SENDNAME = "sendname"; + public static final String CONFIG_KEY_SENDEMAIL = "sendemail"; public static final String usageIdentifyer = LTIManager.class.getCanonicalName(); @@ -91,6 +88,9 @@ public class LTIConfigForm extends FormBasicController { private TextElement tkey; private TextElement tpass; + private MultipleSelectionElement skipLaunchPageEl; + private MultipleSelectionElement skipAcceptLaunchPageEl; + private SelectionElement sendName; private SelectionElement sendEmail; private SelectionElement doDebug; @@ -98,19 +98,25 @@ public class LTIConfigForm extends FormBasicController { private TextElement scaleFactorEl; private TextElement cutValueEl; private MultipleSelectionElement isAssessableEl; - private MultipleSelectionElement authorRoleEl, coachRoleEl, participantRoleEl; + private MultipleSelectionElement authorRoleEl; + private MultipleSelectionElement coachRoleEl; + private MultipleSelectionElement participantRoleEl; private FormLayoutContainer customParamLayout; - private SingleSelection displayEl, heightEl, widthEl; + private SingleSelection displayEl; + private SingleSelection heightEl; + private SingleSelection widthEl; private String fullURI; private Boolean sendNameConfig; private Boolean sendEmailConfig; private Boolean doDebugConfig; private boolean isAssessable; - private String key, pass; + private String key; + private String pass; - private List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); + private List<NameValuePair> nameValuePairs = new ArrayList<>(); + private static final String[] enabledKeys = new String[]{"on"}; private String[] ltiRolesKeys = new String[]{ "Learner", "Instructor", "Administrator", "TeachingAssistant", "ContentDeveloper", "Mentor" @@ -204,7 +210,7 @@ public class LTIConfigForm extends FormBasicController { if (uri != null && uri.length() > 0 && uri.charAt(0) == '/') uri = uri.substring(1); String query = null; - if (configVersion == 2) { + if (configVersion >= 2) { //query string is available since config version 2 query = (String) config.get(LTIConfigForm.CONFIGKEY_QUERY); } @@ -253,11 +259,29 @@ public class LTIConfigForm extends FormBasicController { uifactory.addSpacerElement("attributes", formLayout, false); + String[] enableValues = new String[]{ translate("on") }; + skipLaunchPageEl = uifactory.addCheckboxesHorizontal("display.config.skipLaunchPage", formLayout, enabledKeys, enableValues); + if (config.getBooleanSafe(BasicLTICourseNode.CONFIG_SKIP_LAUNCH_PAGE)) { + skipLaunchPageEl.select(enabledKeys[0], true); + } + + skipAcceptLaunchPageEl = uifactory.addCheckboxesHorizontal("display.config.skipAcceptLaunchPage", formLayout, enabledKeys, enableValues); + if (config.getBooleanSafe(BasicLTICourseNode.CONFIG_SKIP_ACCEPT_LAUNCH_PAGE)) { + skipAcceptLaunchPageEl.select(enabledKeys[0], true); + } + + uifactory.addSpacerElement("attributes", formLayout, false); + sendName = uifactory.addCheckboxesHorizontal("sendName", "display.config.sendName", formLayout, new String[]{"xx"}, new String[]{null}); sendName.select("xx", sendNameConfig); + sendName.addActionListener(FormEvent.ONCHANGE); sendEmail = uifactory.addCheckboxesHorizontal("sendEmail", "display.config.sendEmail", formLayout, new String[]{"xx"}, new String[]{null}); sendEmail.select("xx", sendEmailConfig); + sendEmail.addActionListener(FormEvent.ONCHANGE); + + boolean sendEnabled = sendName.isSelected(0) || sendEmail.isSelected(0); + skipAcceptLaunchPageEl.setVisible(sendEnabled); String page = velocity_root + "/custom.html"; customParamLayout = FormLayoutContainer.createCustomFormLayout("custom_fields", getTranslator(), page); @@ -460,6 +484,7 @@ public class LTIConfigForm extends FormBasicController { return fullURL; } + @SuppressWarnings("unused") @Override protected boolean validateFormLogic(UserRequest ureq) { boolean allOk = true; @@ -500,6 +525,9 @@ public class LTIConfigForm extends FormBasicController { scaleFactorEl.setVisible(assessEnabled); cutValueEl.setVisible(assessEnabled); flc.setDirty(true); + } else if (sendName == source || sendEmail == source) { + boolean sendEnabled = sendName.isSelected(0) || sendEmail.isSelected(0); + skipAcceptLaunchPageEl.setVisible(sendEnabled); } else if(source instanceof FormLink && source.getName().startsWith("add_")) { NameValuePair pair = (NameValuePair)source.getUserObject(); doAddNameValuePair(pair); @@ -551,7 +579,7 @@ public class LTIConfigForm extends FormBasicController { } catch (MalformedURLException e) { throw new OLATRuntimeException("MalformedURL in LTConfigForm which should not happen, since we've validated before. URL: " + thost.getValue(), e); } - config.setConfigurationVersion(2); + config.setConfigurationVersion(BasicLTICourseNode.CURRENT_VERSION); config.set(CONFIGKEY_PROTO, url.getProtocol()); config.set(CONFIGKEY_HOST, url.getHost()); config.set(CONFIGKEY_URI, url.getPath()); @@ -562,8 +590,18 @@ public class LTIConfigForm extends FormBasicController { config.set(CONFIGKEY_PASS, tpass.getValue()); config.set(CONFIG_KEY_DEBUG, Boolean.toString(doDebug.isSelected(0))); config.set(CONFIG_KEY_CUSTOM, getCustomConfig()); + if (skipLaunchPageEl.isAtLeastSelected(1)) { + config.setBooleanEntry(BasicLTICourseNode.CONFIG_SKIP_LAUNCH_PAGE, Boolean.TRUE); + } else { + config.setBooleanEntry(BasicLTICourseNode.CONFIG_SKIP_LAUNCH_PAGE, Boolean.FALSE); + } config.set(CONFIG_KEY_SENDNAME, Boolean.toString(sendName.isSelected(0))); config.set(CONFIG_KEY_SENDEMAIL, Boolean.toString(sendEmail.isSelected(0))); + if (skipAcceptLaunchPageEl.isAtLeastSelected(1) && (sendName.isSelected(0) || sendEmail.isSelected(0))) { + config.setBooleanEntry(BasicLTICourseNode.CONFIG_SKIP_ACCEPT_LAUNCH_PAGE, Boolean.TRUE); + } else { + config.setBooleanEntry(BasicLTICourseNode.CONFIG_SKIP_ACCEPT_LAUNCH_PAGE, Boolean.FALSE); + } if(isAssessableEl.isAtLeastSelected(1)) { config.setBooleanEntry(BasicLTICourseNode.CONFIG_KEY_HAS_SCORE_FIELD, Boolean.TRUE); @@ -583,7 +621,7 @@ public class LTIConfigForm extends FormBasicController { } else { config.setBooleanEntry(BasicLTICourseNode.CONFIG_KEY_HAS_PASSED_FIELD, Boolean.FALSE); config.remove(BasicLTICourseNode.CONFIG_KEY_PASSED_CUT_VALUE); - } + } } else { config.setBooleanEntry(BasicLTICourseNode.CONFIG_KEY_HAS_SCORE_FIELD, Boolean.FALSE); config.setBooleanEntry(BasicLTICourseNode.CONFIG_KEY_HAS_PASSED_FIELD, Boolean.FALSE); @@ -649,10 +687,10 @@ public class LTIConfigForm extends FormBasicController { } private String getFormKey() { - if (StringHelper.containsNonWhitespace(tkey.getValue())) + if (StringHelper.containsNonWhitespace(tkey.getValue())) { return tkey.getValue(); - else - return null; + } + return null; } public static class NameValuePair { diff --git a/src/main/java/org/olat/course/nodes/basiclti/LTIRunController.java b/src/main/java/org/olat/course/nodes/basiclti/LTIRunController.java index 9754398b2b95c67e5b451a76d81ba3ae9bc32673..cc9bb39db9fcd28fd083df64ffe157c9def349e0 100644 --- a/src/main/java/org/olat/course/nodes/basiclti/LTIRunController.java +++ b/src/main/java/org/olat/course/nodes/basiclti/LTIRunController.java @@ -151,15 +151,7 @@ public class LTIRunController extends BasicController { mainPanel = new SimpleStackedPanel("ltiContainer"); putInitialPanel(mainPanel); - - // only run directly when user as already accepted to data exchange or no data has to be exchanged - createExchangeDataProperties(); - String dataExchangeHash = createHashFromExchangeDataProperties(); - if (dataExchangeHash == null || checkHasDataExchangeAccepted(dataExchangeHash)) { - doRun(ureq); - } else { - doAskDataExchange(); - } + doRun(ureq); } /** @@ -353,10 +345,25 @@ public class LTIRunController extends BasicController { boolean resultsVisible = eval.getUserVisible() == null || eval.getUserVisible().booleanValue(); startPage.contextPut("resultsVisible", resultsVisible); mainPanel.setContent(startPage); - } else if(display == LTIDisplayOptions.window) { - mainPanel.setContent(startPage); + } + + // only run when user as already accepted to data exchange or no data + // has to be exchanged or when it is configured to not show the accept + // dialog, + createExchangeDataProperties(); + String dataExchangeHash = createHashFromExchangeDataProperties(); + Boolean skipAcceptLaunchPage = config.getBooleanEntry(BasicLTICourseNode.CONFIG_SKIP_ACCEPT_LAUNCH_PAGE); + if (dataExchangeHash == null || checkHasDataExchangeAccepted(dataExchangeHash) || (skipAcceptLaunchPage != null && skipAcceptLaunchPage.booleanValue()) ) { + Boolean skipLaunchPage = config.getBooleanEntry(BasicLTICourseNode.CONFIG_SKIP_LAUNCH_PAGE); + if(skipLaunchPage != null && skipLaunchPage.booleanValue()) { + // start the content immediately + openBasicLTIContent(ureq); + } else { + // or show the start button + mainPanel.setContent(startPage); + } } else { - openBasicLTIContent(ureq); + doAskDataExchange(); } } diff --git a/src/main/java/org/olat/course/nodes/basiclti/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/basiclti/_i18n/LocalStrings_de.properties index 31bef1f6c0c5aacc1d5cd44121bdcc861ace0988..381dc3b1b8696bfe8fb65e6aefaf3d23107b3c7f 100644 --- a/src/main/java/org/olat/course/nodes/basiclti/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/nodes/basiclti/_i18n/LocalStrings_de.properties @@ -29,6 +29,8 @@ display.config.height=$org.olat.core.gui.control.generic.iframe\:height.label display.config.width=Breite Anzeigefl\u00e4che display.config.free=Text display.config.free.userprops=Benutzer +display.config.skipAcceptLaunchPage=Best\u00e4tigung "Daten\u00fcbertragung" nicht anzeigen +display.config.skipLaunchPage=Inhalt automatisch starten add=+ remove=- height.auto=$org.olat.core.gui.control.generic.iframe\:height.auto @@ -59,29 +61,5 @@ score.yourscore=$org.olat.course.nodes.ms\:score.yourscore passed.yourpassed=$org.olat.course.nodes.ms\:passed.yourpassed passed.no=$org.olat.course.nodes.ms\:passed.no passed.yes=$org.olat.course.nodes.ms\:passed.yes - cshelp.lti1=LTI steht f\u00fcr "Learning Tool Interoperability" und ist ein IMS Standard zur Einbindung von externen Lernapplikationen in eine Lernplattform. - - - - - - - - - - - - - - - - - - - - - condition.accessibility.title=Zugang - - diff --git a/src/main/java/org/olat/course/nodes/basiclti/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/basiclti/_i18n/LocalStrings_en.properties index 480b426449c37d719b2e46582fb430be76bb2fc0..c273f3529af086d9da563c0db131832270fa6c19 100644 --- a/src/main/java/org/olat/course/nodes/basiclti/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/nodes/basiclti/_i18n/LocalStrings_en.properties @@ -15,28 +15,6 @@ add=+ assessable.label=Transfer score attempts.yourattempts=$org.olat.course.nodes.scorm\:attempts.yourattempts author.roles=Author - - - - - - - - - - - - - - - - - - - - - - coach.roles=Coach command.preview=Show preview condition.accessibility.title=Access @@ -54,6 +32,8 @@ display.config.window=Display display.config.window.fullScreen=Display only module, hide LMS (iFrame) display.config.window.iframe=Embedded in course (iFrame) display.config.window.window=Open in new window +display.config.skipAcceptLaunchPage=Skip confirmation "data transfer" +display.config.skipLaunchPage=Skip launch page error.hostmissing.long=In the tab "Page content" a host has to be configured for the external page "{0}" error.hostmissing.short=No host indicated for "{0}". form.error.wrongFloat=$org.olat.course.assessment\:form.error.wrongFloat