Skip to content
Snippets Groups Projects
Commit 54fbbaf7 authored by uhensler's avatar uhensler
Browse files

OO-4836: Opencast course element

parent 3b1c2dae
No related branches found
No related tags found
No related merge requests found
Showing
with 1262 additions and 26 deletions
...@@ -175,4 +175,5 @@ public class AutoCompleterImpl extends AbstractTextElement implements AutoComple ...@@ -175,4 +175,5 @@ public class AutoCompleterImpl extends AbstractTextElement implements AutoComple
return new JSONMediaResource(result, "UTF-8"); return new JSONMediaResource(result, "UTF-8");
} }
} }
} }
\ No newline at end of file
/**
* <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;
import java.util.List;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.stack.BreadcrumbPanel;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.messages.MessageUIFactory;
import org.olat.core.gui.control.generic.tabbable.TabbableController;
import org.olat.core.gui.translator.Translator;
import org.olat.core.util.Util;
import org.olat.core.util.nodes.INode;
import org.olat.course.ICourse;
import org.olat.course.condition.ConditionEditController;
import org.olat.course.editor.ConditionAccessEditConfig;
import org.olat.course.editor.CourseEditorEnv;
import org.olat.course.editor.NodeEditController;
import org.olat.course.editor.StatusDescription;
import org.olat.course.nodes.opencast.ui.OpencastDisplayController;
import org.olat.course.nodes.opencast.ui.OpencastEditController;
import org.olat.course.run.navigation.NodeRunConstructionResult;
import org.olat.course.run.userview.CourseNodeSecurityCallback;
import org.olat.course.run.userview.UserCourseEnvironment;
import org.olat.repository.RepositoryEntry;
/**
*
* Initial date: 11 Aug 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class OpencastCourseNode extends AbstractAccessableCourseNode {
private static final long serialVersionUID = 6660253327851645396L;
@SuppressWarnings("deprecation")
private static final String TRANSLATOR_PACKAGE = Util.getPackageName(OpencastEditController.class);
public static final String TYPE = "opencast";
public static final String ICON_CSS = "o_opencast_icon";
// configuration
public static final String CONFIG_SERIES_IDENTIFIER = "series.identifier";
public static final String CONFIG_EVENT_IDENTIFIER = "event.identifier";
public static final String CONFIG_TITLE = "title";
public OpencastCourseNode() {
this(null);
}
public OpencastCourseNode(INode parent) {
super(TYPE, parent);
}
@Override
public TabbableController createEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel,
ICourse course, UserCourseEnvironment euce) {
OpencastEditController editCtrl = new OpencastEditController(ureq, wControl, this);
CourseNode chosenNode = course.getEditorTreeModel().getCourseNode(euce.getCourseEditorEnv().getCurrentCourseNodeId());
return new NodeEditController(ureq, wControl, course, chosenNode, euce, editCtrl);
}
@Override
public ConditionAccessEditConfig getAccessEditConfig() {
return ConditionAccessEditConfig.regular(false);
}
@Override
public NodeRunConstructionResult createNodeRunConstructionResult(UserRequest ureq, WindowControl wControl,
UserCourseEnvironment userCourseEnv, CourseNodeSecurityCallback nodeSecCallback, String nodecmd) {
Controller runCtrl;
if (userCourseEnv.isCourseReadOnly()) {
Translator trans = Util.createPackageTranslator(OpencastCourseNode.class, ureq.getLocale());
String title = trans.translate("freezenoaccess.title");
String message = trans.translate("freezenoaccess.message");
runCtrl = MessageUIFactory.createInfoMessage(ureq, wControl, title, message);
} else {
runCtrl = new OpencastDisplayController(ureq, wControl, this, userCourseEnv);
}
Controller ctrl = TitledWrapperHelper.getWrapper(ureq, wControl, runCtrl, this, ICON_CSS);
return new NodeRunConstructionResult(ctrl);
}
@SuppressWarnings("deprecation")
@Override
public StatusDescription[] isConfigValid(CourseEditorEnv cev) {
String translatorStr = Util.getPackageName(ConditionEditController.class);
List<StatusDescription> statusDescs = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
return StatusDescriptionHelper.sort(statusDescs);
}
@Override
public StatusDescription isConfigValid() {
if (oneClickStatusCache != null) {
return oneClickStatusCache[0];
}
StatusDescription sd = StatusDescription.NOERROR;
boolean isSelected = getModuleConfiguration().has(CONFIG_SERIES_IDENTIFIER)
|| getModuleConfiguration().has(CONFIG_EVENT_IDENTIFIER);
if (!isSelected) {
String shortKey = "error.no.selection.short";
String longKey = "error.no.selection.long";
String[] params = new String[] { this.getShortTitle() };
sd = new StatusDescription(StatusDescription.ERROR, shortKey, longKey, params, TRANSLATOR_PACKAGE);
sd.setDescriptionForUnit(getIdent());
// set which pane is affected by error
sd.setActivateableViewIdentifier(OpencastEditController.PANE_TAB_CONFIG);
}
return sd;
}
@Override
public RepositoryEntry getReferencedRepositoryEntry() {
return null;
}
@Override
public boolean needsReferenceToARepositoryEntry() {
return false;
}
}
...@@ -100,7 +100,11 @@ ...@@ -100,7 +100,11 @@
<bean id="livestream" class="org.olat.course.nodes.livestream.LiveStreamCourseNodeConfiguration" scope="prototype"> <bean id="livestream" class="org.olat.course.nodes.livestream.LiveStreamCourseNodeConfiguration" scope="prototype">
<property name="order" value="222" /> <property name="order" value="222" />
</bean> </bean>
<bean id="opencast" class="org.olat.course.nodes.opencast.OpencastCourseNodeConfiguration" scope="prototype">
<property name="order" value="223" />
</bean>
<bean id="edusharing" class="org.olat.course.nodes.edusharing.EdusharingCourseNodeConfiguration" scope="prototype"> <bean id="edusharing" class="org.olat.course.nodes.edusharing.EdusharingCourseNodeConfiguration" scope="prototype">
<property name="order" value="224" /> <property name="order" value="224" />
</bean> </bean>
......
/**
* <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.opencast;
import org.olat.course.learningpath.LearningPathOnlyAssessmentHandler;
import org.olat.course.nodes.OpencastCourseNode;
import org.springframework.stereotype.Service;
/**
*
* Initial date: 11.09.2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
@Service
public class OpencastAssessmentHandler extends LearningPathOnlyAssessmentHandler {
@Override
public String acceptCourseNodeType() {
return OpencastCourseNode.TYPE;
}
}
/**
* <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>
* 12.10.2011 by frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.course.nodes.opencast;
import java.util.Locale;
import org.olat.core.CoreSpringFactory;
import org.olat.core.gui.translator.Translator;
import org.olat.core.util.Util;
import org.olat.core.util.nodes.INode;
import org.olat.course.nodes.AbstractCourseNodeConfiguration;
import org.olat.course.nodes.CourseNode;
import org.olat.course.nodes.CourseNodeConfiguration;
import org.olat.course.nodes.CourseNodeGroup;
import org.olat.course.nodes.OpencastCourseNode;
import org.olat.course.nodes.opencast.ui.OpencastEditController;
import org.olat.modules.opencast.OpencastModule;
/**
*
* Initial date: 11.08.2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class OpencastCourseNodeConfiguration extends AbstractCourseNodeConfiguration {
private final String alias;
public OpencastCourseNodeConfiguration() {
this("opencast");
}
public OpencastCourseNodeConfiguration(String alias) {
this.alias = alias;
}
@Override
public String getAlias() {
return alias;
}
@Override
public String getGroup() {
return CourseNodeGroup.content.name();
}
@Override
public String getIconCSSClass() {
return OpencastCourseNode.ICON_CSS;
}
@Override
public CourseNode getInstance(INode parent) {
return new OpencastCourseNode();
}
@Override
public String getLinkText(Locale locale) {
Translator fallback = Util.createPackageTranslator(CourseNodeConfiguration.class, locale);
Translator translator = Util.createPackageTranslator(OpencastEditController.class, locale, fallback);
return translator.translate("title");
}
@Override
public boolean isEnabled() {
return CoreSpringFactory.getImpl(OpencastModule.class).isCourseNodeEnabled();
}
}
\ No newline at end of file
/**
* <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.opencast;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl;
import org.olat.course.learningpath.LearningPathConfigs;
import org.olat.course.learningpath.LearningPathEditConfigs;
import org.olat.course.learningpath.LearningPathNodeHandler;
import org.olat.course.learningpath.model.ModuleLearningPathConfigs;
import org.olat.course.learningpath.ui.LearningPathNodeConfigController;
import org.olat.course.nodes.CourseNode;
import org.olat.course.nodes.OpencastCourseNode;
import org.olat.repository.RepositoryEntry;
import org.springframework.stereotype.Service;
/**
*
* Initial date: 11.09.2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
@Service
public class OpencastLearningPathNodeHandler implements LearningPathNodeHandler {
private static final LearningPathEditConfigs EDIT_CONFIGS = LearningPathEditConfigs.builder()
.enableNodeVisited()
.enableConfirmed()
.build();
@Override
public String acceptCourseNodeType() {
return OpencastCourseNode.TYPE;
}
@Override
public boolean isSupported() {
return true;
}
@Override
public LearningPathConfigs getConfigs(CourseNode courseNode) {
return new ModuleLearningPathConfigs(courseNode.getModuleConfiguration(), true);
}
@Override
public Controller createConfigEditController(UserRequest ureq, WindowControl wControl, RepositoryEntry courseEntry,
CourseNode courseNode) {
return new LearningPathNodeConfigController(ureq, wControl, courseEntry, courseNode, EDIT_CONFIGS);
}
@Override
public LearningPathEditConfigs getEditConfigs() {
return EDIT_CONFIGS;
}
@Override
public void onMigrated(CourseNode courseNode) {
//
}
}
/**
* <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.opencast.ui;
import static org.olat.core.gui.translator.TranslatorHelper.translateAll;
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.AutoCompleter;
import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
import org.olat.core.gui.components.form.flexible.elements.StaticTextElement;
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.AutoCompleteFormEvent;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.util.StringHelper;
import org.olat.course.editor.NodeEditController;
import org.olat.course.nodes.OpencastCourseNode;
import org.olat.modules.ModuleConfiguration;
import org.olat.modules.opencast.OpencastEvent;
import org.olat.modules.opencast.OpencastEventProvider;
import org.olat.modules.opencast.OpencastSeries;
import org.olat.modules.opencast.OpencastSeriesProvider;
import org.olat.modules.opencast.OpencastService;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 11 Aug 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class OpencastConfigController extends FormBasicController {
private static final String DISPLAY_KEY_SERIES = "config.display.series";
private static final String DISPLAY_KEY_EVENT = "config.display.event";
private static final String[] DISPLAY_KEYS = new String[] {
DISPLAY_KEY_SERIES,
DISPLAY_KEY_EVENT
};
private static final String MORE_KEY = ".....";
private SingleSelection displayEl;
private AutoCompleter seriesEl;
private AutoCompleter eventEl;
private StaticTextElement identifierEl;
private final ModuleConfiguration config;
@Autowired
private OpencastService opencastService;
public OpencastConfigController(UserRequest ureq, WindowControl wControl, OpencastCourseNode courseNode) {
super(ureq, wControl);
config = courseNode.getModuleConfiguration();
initForm(ureq);
updateUI();
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
displayEl = uifactory.addRadiosVertical("config.display", formLayout, DISPLAY_KEYS, translateAll(getTranslator(), DISPLAY_KEYS));
displayEl.addActionListener(FormEvent.ONCHANGE);
String selectedKey = config.has(OpencastCourseNode.CONFIG_EVENT_IDENTIFIER)? DISPLAY_KEY_EVENT: DISPLAY_KEY_SERIES;
displayEl.select(selectedKey, true);
String seriesIdentifier = config.getStringValue(OpencastCourseNode.CONFIG_SERIES_IDENTIFIER, null);
String seriesTitle = null;
if (seriesIdentifier != null) {
OpencastSeries series = opencastService.getSeries(seriesIdentifier);
if (series != null) {
seriesTitle = series.getTitle();
}
}
seriesEl = uifactory.addTextElementWithAutoCompleter("config.series", "config.series", 128, seriesTitle, formLayout);
seriesEl.setListProvider(new OpencastSeriesProvider(getIdentity(), MORE_KEY), ureq.getUserSession());
seriesEl.setKey(seriesIdentifier);
seriesEl.setMinLength(1);
String eventIdentifier = config.getStringValue(OpencastCourseNode.CONFIG_EVENT_IDENTIFIER, null);
String eventTitle = null;
if (eventIdentifier != null) {
OpencastEvent event = opencastService.getEvent(eventIdentifier);
if (event != null) {
eventTitle = event.getTitle();
}
}
eventEl = uifactory.addTextElementWithAutoCompleter("config.event", "config.event", 128, eventTitle, formLayout);
eventEl.setListProvider(new OpencastEventProvider(getIdentity(), MORE_KEY), ureq.getUserSession());
eventEl.setKey(eventIdentifier);
eventEl.setMinLength(1);
String identifier = null;
if (StringHelper.containsNonWhitespace(seriesIdentifier)) {
identifier = seriesIdentifier;
} else if (StringHelper.containsNonWhitespace(eventIdentifier)) {
identifier = eventIdentifier;
}
identifierEl = uifactory.addStaticTextElement("config.identifier", identifier, formLayout);
FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
formLayout.add(buttonsCont);
uifactory.addFormSubmitButton("save", buttonsCont);
}
private void updateUI() {
boolean seriesSelected = displayEl.isOneSelected() && displayEl.getSelectedKey().equals(DISPLAY_KEY_SERIES);
seriesEl.setVisible(seriesSelected);
eventEl.setVisible(!seriesSelected);
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if (source == displayEl) {
identifierEl.setValue("");
updateUI();
} else if (source == seriesEl || source == eventEl) {
if (event instanceof AutoCompleteFormEvent) {
String key = ((AutoCompleteFormEvent)event).getKey();
if (!MORE_KEY.equals(key)) {
identifierEl.setValue(key);
}
}
}
super.formInnerEvent(ureq, source, event);
}
@Override
protected boolean validateFormLogic(UserRequest ureq) {
boolean allOk = super.validateFormLogic(ureq);
seriesEl.clearError();
eventEl.clearError();
boolean seriesSelected = displayEl.isOneSelected() && displayEl.getSelectedKey().equals(DISPLAY_KEY_SERIES);
if (seriesSelected) {
if (!StringHelper.containsNonWhitespace(seriesEl.getValue())) {
seriesEl.setErrorKey("form.legende.mandatory", null);
allOk &= false;
}
} else {
if (!StringHelper.containsNonWhitespace(eventEl.getValue())) {
eventEl.setErrorKey("form.legende.mandatory", null);
allOk &= false;
}
}
return allOk;
}
@Override
protected void formOK(UserRequest ureq) {
boolean seriesSelected = displayEl.isOneSelected() && displayEl.getSelectedKey().equals(DISPLAY_KEY_SERIES);
if (seriesSelected) {
String seriesIdentifier = seriesEl.getKey();
config.setStringValue(OpencastCourseNode.CONFIG_SERIES_IDENTIFIER, seriesIdentifier);
String title = seriesEl.getValue();
config.setStringValue(OpencastCourseNode.CONFIG_TITLE, title);
config.remove(OpencastCourseNode.CONFIG_EVENT_IDENTIFIER);
} else {
String eventIdentifier = eventEl.getKey();
config.setStringValue(OpencastCourseNode.CONFIG_EVENT_IDENTIFIER, eventIdentifier);
String title = eventEl.getValue();
config.setStringValue(OpencastCourseNode.CONFIG_TITLE, title);
config.remove(OpencastCourseNode.CONFIG_SERIES_IDENTIFIER);
}
fireEvent(ureq, NodeEditController.NODECONFIG_CHANGED_EVENT);
}
@Override
protected void doDispose() {
//
}
}
/**
* <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.opencast.ui;
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.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.WindowControl;
import org.olat.core.gui.control.winmgr.CommandFactory;
import org.olat.core.util.Formatter;
import org.olat.course.nodes.OpencastCourseNode;
import org.olat.course.run.userview.UserCourseEnvironment;
import org.olat.modules.ModuleConfiguration;
import org.olat.modules.opencast.OpencastEvent;
import org.olat.modules.opencast.OpencastModule;
import org.olat.modules.opencast.OpencastSeries;
import org.olat.modules.opencast.OpencastService;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 12 Aug 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class OpencastDisplayController extends FormBasicController {
private FormLink seriesButton;
private FormLink eventButton;
private final ModuleConfiguration config;
private final String roles;
@Autowired
private OpencastModule opencastModule;
@Autowired
private OpencastService opencastService;
public OpencastDisplayController(UserRequest ureq, WindowControl wControl, OpencastCourseNode courseNode,
UserCourseEnvironment userCourseEnv) {
super(ureq, wControl, "display");
config = courseNode.getModuleConfiguration();
roles = initRoles(userCourseEnv);
initForm(ureq);
doStartImmediately(ureq);
}
private String initRoles(UserCourseEnvironment userCourseEnv) {
if (userCourseEnv.isAdmin()) {
return opencastModule.getRolesAdmin();
} else if (userCourseEnv.isCoach()) {
return opencastModule.getRolesCoach();
}
return opencastModule.getRolesParticipant();
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
if (formLayout instanceof FormLayoutContainer) {
FormLayoutContainer layoutCont = (FormLayoutContainer)formLayout;
String title = config.getStringValue(OpencastCourseNode.CONFIG_TITLE);
layoutCont.contextPut("title", title);
if (config.has(OpencastCourseNode.CONFIG_SERIES_IDENTIFIER)) {
String seriesIdentifier = config.getStringValue(OpencastCourseNode.CONFIG_SERIES_IDENTIFIER);
OpencastSeries series = opencastService.getSeries(seriesIdentifier);
if (series != null) {
layoutCont.contextPut("title", series.getTitle());
seriesButton = uifactory.addFormLink("start.series", formLayout, Link.BUTTON_LARGE);
seriesButton.setNewWindow(true, true);
seriesButton.setUserObject(series);
} else {
layoutCont.contextPut("error", translate("error.series.not.found", new String[] {title}));
}
} else {
String eventIdentifier = config.getStringValue(OpencastCourseNode.CONFIG_EVENT_IDENTIFIER);
OpencastEvent event = opencastService.getEvent(eventIdentifier);
if (event != null) {
layoutCont.contextPut("title", event.getTitle());
String start = Formatter.getInstance(getLocale()).formatDateAndTime(event.getStart());
layoutCont.contextPut("start", start);
layoutCont.contextPut("creator", event.getCreator());
eventButton = uifactory.addFormLink("start.event", formLayout, Link.BUTTON_LARGE);
eventButton.setNewWindow(true, true);
eventButton.setUserObject(event);
} else {
layoutCont.contextPut("error", translate("error.event.not.found", new String[] {title}));
}
}
}
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if (source == seriesButton) {
OpencastSeries opencastSeries = (OpencastSeries)seriesButton.getUserObject();
doStartSeries(ureq, opencastSeries);
} else if (source == eventButton) {
OpencastEvent opencastEvent = (OpencastEvent)eventButton.getUserObject();
doStartEvent(ureq, opencastEvent);
}
super.formInnerEvent(ureq, source, event);
}
private void doStartImmediately(UserRequest ureq) {
if (opencastModule.isStartImmediately()) {
if (seriesButton != null) {
OpencastSeries opencastSeries = (OpencastSeries)seriesButton.getUserObject();
doStartSeries(ureq, opencastSeries);
} else if (eventButton != null) {
OpencastEvent opencastEvent = (OpencastEvent)eventButton.getUserObject();
doStartEvent(ureq, opencastEvent);
}
}
}
private void doStartSeries(UserRequest ureq, OpencastSeries opencastSeries) {
String url = opencastService.getLtiSeriesMapperUrl(ureq.getUserSession(), opencastSeries, roles);
getWindowControl().getWindowBackOffice().sendCommandTo(CommandFactory.createNewWindowRedirectTo(url));
}
private void doStartEvent(UserRequest ureq, OpencastEvent opencastEvent) {
String url = opencastService.getLtiEventMapperUrl(ureq.getUserSession(), opencastEvent.getIdentifier(), roles);
getWindowControl().getWindowBackOffice().sendCommandTo(CommandFactory.createNewWindowRedirectTo(url));
}
@Override
protected void formOK(UserRequest ureq) {
//
}
@Override
protected void doDispose() {
//
}
}
/**
* <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.opencast.ui;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.tabbedpane.TabbedPane;
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.tabbable.ActivateableTabbableDefaultController;
import org.olat.course.nodes.OpencastCourseNode;
/**
*
* Initial date: 11.08.2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class OpencastEditController extends ActivateableTabbableDefaultController {
public static final String PANE_TAB_CONFIG = "pane.tab.config";
private static final String[] paneKeys = { PANE_TAB_CONFIG };
private TabbedPane tabPane;
private OpencastConfigController configCtrl;
public OpencastEditController(UserRequest ureq, WindowControl wControl, OpencastCourseNode courseNode) {
super(ureq, wControl);
configCtrl = new OpencastConfigController(ureq, wControl, courseNode);
listenTo(configCtrl);
}
@Override
public String[] getPaneKeys() {
return paneKeys;
}
@Override
public TabbedPane getTabbedPane() {
return tabPane;
}
@Override
protected void doDispose() {
//
}
@Override
protected void event(UserRequest ureq, Component source, Event event) {
//
}
@Override
public void event(UserRequest ureq, Controller source, Event event) {
if (source == configCtrl) {
fireEvent(ureq, event);
}
}
@Override
public void addTabs(TabbedPane tabbedPane) {
tabPane = tabbedPane;
tabbedPane.addTab(translate(PANE_TAB_CONFIG), configCtrl.getInitialComponent());
}
}
<div>
<h3>$r.escapeHtml($title)</h3>
#if($r.isNotEmpty($errorMessage))
<div class="o_error">$errorMessage</div>
#end
#if($r.isNotNull($start))
<div><i class="o_icon o_icon-fw o_icon_lifecycle_date"> </i> $start</div>
#end
#if($r.isNotEmpty($creator))
<div><i class="o_icon o_icon-fw o_icon_user"> </i> $r.escapeHtml($creator)</div>
#end
<div class="o_button_group">
#if($r.available("start.series") && $r.visible("start.series"))
$r.render("start.series")
#end
#if($r.available("start.event") && $r.visible("start.event"))
$r.render("start.event")
#end
</div>
</div>
\ No newline at end of file
config.display=Anzeige
config.display.event=Video
config.display.series=Serie
config.event=Video
config.identifier=Identifikation
config.series=Serie
error.event.not.found=Das Video "{0}" konnte in Opencast nicht gefunden werden.
error.no.selection.long=F\u00fcr "{0}" muss in der Konfiguration ein Video oder eine Serie im Reiter "Konfiguration" ausgew\u00e4hlt werden.
error.no.selection.short=Es ist weder ein Video noch eine Serie ausw\u00e4hlt.
error.series.not.found=Die Serie "{0}" konnte in Opencast nicht gefunden werden.
pane.tab.config=Konfiguration
start.event=Video starten
start.series=Serie \u00f6ffnen
title=Opencast
config.display=Display
config.display.event=Video
config.display.series=Series
config.event=Video
config.identifier=Identifier
config.series=Series
error.event.not.found=The event "{0}" was not found on Opencast.
error.no.selection.long=For "{0}" a video or a series must be selected in the configuration in the "Configuration" tab.
error.no.selection.short=It is neither a video nor a series selected.
error.series.not.found=The series "{0}" was not found on Opencast.
pane.tab.config=Configuration
start.event=Start video
start.series=Open series
title=Opencast
...@@ -249,7 +249,7 @@ public class BusinessGroupRelationDAO { ...@@ -249,7 +249,7 @@ public class BusinessGroupRelationDAO {
* Match the list of roles with the list of specfified roles * Match the list of roles with the list of specfified roles
* @param identity * @param identity
* @param group * @param group
* @param roles * @param Roles
* @return * @return
*/ */
public boolean hasRole(IdentityRef identity, BusinessGroupRef group, String role) { public boolean hasRole(IdentityRef identity, BusinessGroupRef group, String role) {
......
...@@ -24,12 +24,8 @@ import java.util.Collections; ...@@ -24,12 +24,8 @@ import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.olat.core.dispatcher.mapper.Mapper;
import org.olat.core.dispatcher.mapper.MapperService;
import org.olat.core.dispatcher.mapper.manager.MapperKey;
import org.olat.core.gui.translator.Translator; import org.olat.core.gui.translator.Translator;
import org.olat.core.id.User; import org.olat.core.id.User;
import org.olat.core.id.UserConstants; import org.olat.core.id.UserConstants;
...@@ -42,9 +38,6 @@ import org.olat.course.CourseFactory; ...@@ -42,9 +38,6 @@ import org.olat.course.CourseFactory;
import org.olat.course.ICourse; import org.olat.course.ICourse;
import org.olat.course.nodes.CourseNode; import org.olat.course.nodes.CourseNode;
import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroup;
import org.olat.ims.lti.LTIContext;
import org.olat.ims.lti.LTIManager;
import org.olat.ims.lti.ui.PostDataMapper;
import org.olat.modules.bigbluebutton.BigBlueButtonMeeting; import org.olat.modules.bigbluebutton.BigBlueButtonMeeting;
import org.olat.modules.bigbluebutton.BigBlueButtonRecording; import org.olat.modules.bigbluebutton.BigBlueButtonRecording;
import org.olat.modules.bigbluebutton.BigBlueButtonRecordingsHandler; import org.olat.modules.bigbluebutton.BigBlueButtonRecordingsHandler;
...@@ -53,7 +46,6 @@ import org.olat.modules.bigbluebutton.model.BigBlueButtonErrorCodes; ...@@ -53,7 +46,6 @@ import org.olat.modules.bigbluebutton.model.BigBlueButtonErrorCodes;
import org.olat.modules.bigbluebutton.model.BigBlueButtonErrors; import org.olat.modules.bigbluebutton.model.BigBlueButtonErrors;
import org.olat.modules.bigbluebutton.model.BigBlueButtonRecordingImpl; import org.olat.modules.bigbluebutton.model.BigBlueButtonRecordingImpl;
import org.olat.modules.bigbluebutton.ui.BigBlueButtonAdminController; import org.olat.modules.bigbluebutton.ui.BigBlueButtonAdminController;
import org.olat.modules.opencast.OpencastBBBRecordingContext;
import org.olat.modules.opencast.OpencastEvent; import org.olat.modules.opencast.OpencastEvent;
import org.olat.modules.opencast.OpencastModule; import org.olat.modules.opencast.OpencastModule;
import org.olat.modules.opencast.OpencastService; import org.olat.modules.opencast.OpencastService;
...@@ -80,10 +72,6 @@ public class BigBlueButtonOpenCastRecordingsHandler implements BigBlueButtonReco ...@@ -80,10 +72,6 @@ public class BigBlueButtonOpenCastRecordingsHandler implements BigBlueButtonReco
private OpencastModule opencastModule; private OpencastModule opencastModule;
@Autowired @Autowired
private OpencastService opencastService; private OpencastService opencastService;
@Autowired
private LTIManager ltiManager;
@Autowired
private MapperService mapperService;
@Override @Override
public String getId() { public String getId() {
...@@ -108,7 +96,7 @@ public class BigBlueButtonOpenCastRecordingsHandler implements BigBlueButtonReco ...@@ -108,7 +96,7 @@ public class BigBlueButtonOpenCastRecordingsHandler implements BigBlueButtonReco
@Override @Override
public List<BigBlueButtonRecording> getRecordings(BigBlueButtonMeeting meeting, BigBlueButtonErrors errors) { public List<BigBlueButtonRecording> getRecordings(BigBlueButtonMeeting meeting, BigBlueButtonErrors errors) {
if(!opencastModule.isEnabled()) { if(!opencastModule.isBigBlueButtonEnabled()) {
log.error("Try getting recordings of disabled Opencast: {}", opencastModule.getApiUrl()); log.error("Try getting recordings of disabled Opencast: {}", opencastModule.getApiUrl());
errors.append(new BigBlueButtonError(BigBlueButtonErrorCodes.opencastDisabled)); errors.append(new BigBlueButtonError(BigBlueButtonErrorCodes.opencastDisabled));
return Collections.emptyList(); return Collections.emptyList();
...@@ -131,11 +119,7 @@ public class BigBlueButtonOpenCastRecordingsHandler implements BigBlueButtonReco ...@@ -131,11 +119,7 @@ public class BigBlueButtonOpenCastRecordingsHandler implements BigBlueButtonReco
@Override @Override
public String getRecordingURL(UserSession usess, BigBlueButtonRecording recording) { public String getRecordingURL(UserSession usess, BigBlueButtonRecording recording) {
LTIContext context = new OpencastBBBRecordingContext(recording.getRecordId()); return opencastService.getLtiEventMapperUrl(usess, recording.getRecordId(), "Learner");
Map<String,String> unsignedProps = ltiManager.forgeLTIProperties(usess.getIdentity(), usess.getLocale(), context, false, false, true);
Mapper contentMapper = new PostDataMapper(unsignedProps, opencastModule.getLtiUrl(), opencastModule.getLtiKey(), opencastModule.getLtiSecret(), false);
MapperKey mapperKey = mapperService.register(usess, contentMapper);
return mapperKey.getUrl();
} }
@Override @Override
...@@ -215,7 +199,7 @@ public class BigBlueButtonOpenCastRecordingsHandler implements BigBlueButtonReco ...@@ -215,7 +199,7 @@ public class BigBlueButtonOpenCastRecordingsHandler implements BigBlueButtonReco
@Override @Override
public boolean deleteRecordings(List<BigBlueButtonRecording> recordings, BigBlueButtonMeeting meeting, BigBlueButtonErrors errors) { public boolean deleteRecordings(List<BigBlueButtonRecording> recordings, BigBlueButtonMeeting meeting, BigBlueButtonErrors errors) {
if (!opencastModule.isEnabled()) { if (!opencastModule.isBigBlueButtonEnabled()) {
log.error("Try deleting a recording of disabled Opencast: {}", opencastModule.getApiUrl()); log.error("Try deleting a recording of disabled Opencast: {}", opencastModule.getApiUrl());
errors.append(new BigBlueButtonError(BigBlueButtonErrorCodes.opencastDisabled)); errors.append(new BigBlueButtonError(BigBlueButtonErrorCodes.opencastDisabled));
return false; return false;
......
/**
* <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.modules.opencast;
/**
*
* Initial date: 13 Aug 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class AuthDelegate {
public enum Type {
None, User, Roles;
static public boolean isValid(String name) {
for (Type type : Type.values())
if (type.name().equals(name)) {
return true;
}
return false;
}
};
private final Type type;
private final String value;
public static AuthDelegate of(Type type, String value) {
return new AuthDelegate(type, value);
}
private AuthDelegate(Type type, String value) {
super();
this.type = type;
this.value = value;
}
public Type getType() {
return type;
}
public String getValue() {
return value;
}
}
...@@ -33,8 +33,10 @@ public interface OpencastEvent { ...@@ -33,8 +33,10 @@ public interface OpencastEvent {
String getTitle(); String getTitle();
String getCreator();
Date getStart(); Date getStart();
Date getEnd(); Date getEnd();
} }
/**
* <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.modules.opencast;
import java.util.List;
import java.util.stream.Collectors;
import org.olat.core.CoreSpringFactory;
import org.olat.core.gui.control.generic.ajax.autocompletion.ListProvider;
import org.olat.core.gui.control.generic.ajax.autocompletion.ListReceiver;
import org.olat.core.id.Identity;
/**
*
* Initial date: 11 Aug 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class OpencastEventProvider implements ListProvider {
private static final int LIMIT = 15;
private final String moreKey;
private final AuthDelegate authDelegate;
private List<OpencastEvent> events;
private final OpencastService opencastService;
public OpencastEventProvider(Identity identity, String moreKey) {
this.moreKey = moreKey;
opencastService = CoreSpringFactory.getImpl(OpencastService.class);
authDelegate = opencastService.getAuthDelegate(identity);
}
@Override
public int getMaxEntries() {
return LIMIT;
}
@Override
public void getResult(String searchValue, ListReceiver receiver) {
// Opencast does not support wildcards in filters. So we load all events
// and filter them here.
if (events == null) {
events = opencastService.getEvents(authDelegate);
}
List<OpencastEvent> matchingEvents = events.stream()
.filter(e -> e.getTitle().toLowerCase().indexOf(searchValue.toLowerCase()) > -1)
.sorted((e1, e2) -> e1.getTitle().compareToIgnoreCase(e2.getTitle()))
.collect(Collectors.toList());
List<OpencastEvent> limitedEvents = matchingEvents.stream()
.limit(LIMIT)
.collect(Collectors.toList());
limitedEvents.forEach(e -> receiver.addEntry(e.getIdentifier(), e.getTitle()));
if (matchingEvents.size() > limitedEvents.size()) {
receiver.addEntry(moreKey, moreKey);
}
}
}
...@@ -28,6 +28,7 @@ import org.olat.core.configuration.ConfigOnOff; ...@@ -28,6 +28,7 @@ import org.olat.core.configuration.ConfigOnOff;
import org.olat.core.logging.Tracing; import org.olat.core.logging.Tracing;
import org.olat.core.util.StringHelper; import org.olat.core.util.StringHelper;
import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.modules.opencast.AuthDelegate.Type;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -35,7 +36,7 @@ import org.springframework.stereotype.Service; ...@@ -35,7 +36,7 @@ import org.springframework.stereotype.Service;
/** /**
* *
* Initial date: 4 Aug 2020<br> * Initial date: 4 Aug 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com * @admin uhensler, urs.hensler@frentix.com, http://www.frentix.com
* *
*/ */
@Service @Service
...@@ -48,8 +49,17 @@ public class OpencastModule extends AbstractSpringModule implements ConfigOnOff ...@@ -48,8 +49,17 @@ public class OpencastModule extends AbstractSpringModule implements ConfigOnOff
private static final String API_USERNAME = "api.username"; private static final String API_USERNAME = "api.username";
private static final String API_PASSOWRD = "api.password"; private static final String API_PASSOWRD = "api.password";
private static final String LTI_URL = "lti.url"; private static final String LTI_URL = "lti.url";
private static final String LTI_SIGN_URL = "lti.sign.url";
private static final String LTI_KEY = "lti.key"; private static final String LTI_KEY = "lti.key";
private static final String LTI_SECRET = "lti.secret"; private static final String LTI_SECRET = "lti.secret";
private static final String BBB_ENABLED = "opencast.bbb.enabled";
private static final String COURSE_NODE_ENABLED = "opencast.course.node.enabled";
private static final String START_IMMEDIATELY = "start.immediately";
private static final String ROLES_ADMIN = "roles.admin";
private static final String ROLES_COACH = "roles.coach";
private static final String ROLES_PARTICIPANT = "roles.participant";
private static final String AUTH_DELEGATE_TYPE = "auth.delegate";
private static final String AUTH_DELEGATE_ROLES = "auth.delegate.roles";
@Value("${opencast.enabled}") @Value("${opencast.enabled}")
private boolean enabled; private boolean enabled;
...@@ -61,10 +71,28 @@ public class OpencastModule extends AbstractSpringModule implements ConfigOnOff ...@@ -61,10 +71,28 @@ public class OpencastModule extends AbstractSpringModule implements ConfigOnOff
private String apiPassword; private String apiPassword;
@Value("${opencast.lti.url}") @Value("${opencast.lti.url}")
private String ltiUrl; private String ltiUrl;
@Value("${opencast.lti.sign.url}")
private String ltiSignUrl;
@Value("${opencast.lti.key}") @Value("${opencast.lti.key}")
private String ltiKey; private String ltiKey;
@Value("${opencast.lti.secret}") @Value("${opencast.lti.secret}")
private String ltiSecret; private String ltiSecret;
@Value("${opencast.bbb.enabled}")
private boolean bigBlueButtonEnabled;
@Value("${opencast.course.node.enabled}")
private boolean courseNodeEnabled;
@Value("${opencast.course.node.start.immediately}")
private boolean startImmediately;
@Value("${opencast.course.node.roles.admin}")
private String rolesAdmin;
@Value("${opencast.course.node.roles.coach}")
private String rolesCoach;
@Value("${opencast.course.node.roles.participant}")
private String rolesParticipant;
@Value("${opencast.course.node.auth.delegate}")
private Type authDelegateType;
@Value("${opencast.course.node.auth.delegate.roles}")
private String authDelegateRoles;
private String apiAuthorizationHeader; private String apiAuthorizationHeader;
...@@ -83,11 +111,39 @@ public class OpencastModule extends AbstractSpringModule implements ConfigOnOff ...@@ -83,11 +111,39 @@ public class OpencastModule extends AbstractSpringModule implements ConfigOnOff
apiUrl = getStringPropertyValue(API_URL, apiUrl); apiUrl = getStringPropertyValue(API_URL, apiUrl);
apiUsername = getStringPropertyValue(API_USERNAME, apiUsername); apiUsername = getStringPropertyValue(API_USERNAME, apiUsername);
apiPassword = getStringPropertyValue(API_PASSOWRD, apiPassword); apiPassword = getStringPropertyValue(API_PASSOWRD, apiPassword);
refreshApiAutorization(); refreshApiAuthorization();
ltiUrl = getStringPropertyValue(LTI_URL, ltiUrl); ltiUrl = getStringPropertyValue(LTI_URL, ltiUrl);
ltiSignUrl = getStringPropertyValue(LTI_SIGN_URL, ltiSignUrl);
ltiKey = getStringPropertyValue(LTI_KEY, ltiKey); ltiKey = getStringPropertyValue(LTI_KEY, ltiKey);
ltiSecret = getStringPropertyValue(LTI_SECRET, ltiSecret); ltiSecret = getStringPropertyValue(LTI_SECRET, ltiSecret);
String bbbEnabledObj = getStringPropertyValue(BBB_ENABLED, true);
if(StringHelper.containsNonWhitespace(bbbEnabledObj)) {
bigBlueButtonEnabled = "true".equals(bbbEnabledObj);
}
String courseNodeEnabledObj = getStringPropertyValue(COURSE_NODE_ENABLED, true);
if(StringHelper.containsNonWhitespace(courseNodeEnabledObj)) {
courseNodeEnabled = "true".equals(courseNodeEnabledObj);
}
String startImmediatelyObj = getStringPropertyValue(START_IMMEDIATELY, true);
if(StringHelper.containsNonWhitespace(startImmediatelyObj)) {
startImmediately = "true".equals(startImmediatelyObj);
}
rolesAdmin = getStringPropertyValue(ROLES_ADMIN, rolesAdmin);
rolesCoach = getStringPropertyValue(ROLES_COACH, rolesCoach);
rolesParticipant = getStringPropertyValue(ROLES_PARTICIPANT, rolesParticipant);
String authDelegateObj = getStringPropertyValue(AUTH_DELEGATE_TYPE, true);
if (StringHelper.containsNonWhitespace(authDelegateObj) && AuthDelegate.Type.isValid(authDelegateObj)) {
authDelegateType = Type.valueOf(authDelegateObj);
} else {
authDelegateType = Type.User;
}
authDelegateRoles = getStringPropertyValue(AUTH_DELEGATE_ROLES, authDelegateRoles);
} }
@Override @Override
...@@ -129,14 +185,14 @@ public class OpencastModule extends AbstractSpringModule implements ConfigOnOff ...@@ -129,14 +185,14 @@ public class OpencastModule extends AbstractSpringModule implements ConfigOnOff
this.apiPassword = apiPassword; this.apiPassword = apiPassword;
setSecretStringProperty(API_PASSOWRD, apiPassword, true); setSecretStringProperty(API_PASSOWRD, apiPassword, true);
refreshApiAutorization(); refreshApiAuthorization();
} }
/* /*
* Did not work with BasicCredentialsProvider!? * Did not work with BasicCredentialsProvider!?
* So let's create the AUTHORIZATION header by ourself. * So let's create the AUTHORIZATION header by ourself.
*/ */
private void refreshApiAutorization() { private void refreshApiAuthorization() {
try { try {
String auth = apiUsername + ":" + apiPassword; String auth = apiUsername + ":" + apiPassword;
byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.ISO_8859_1)); byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.ISO_8859_1));
...@@ -159,6 +215,19 @@ public class OpencastModule extends AbstractSpringModule implements ConfigOnOff ...@@ -159,6 +215,19 @@ public class OpencastModule extends AbstractSpringModule implements ConfigOnOff
setStringProperty(LTI_URL, ltiUrl, true); setStringProperty(LTI_URL, ltiUrl, true);
} }
public String getLtiSignUrl() {
return StringHelper.containsNonWhitespace(ltiSignUrl)? ltiSignUrl: ltiUrl;
}
public String getLtiSignUrlRaw() {
return ltiSignUrl;
}
public void setLtiSignUrl(String ltiSignUrl) {
this.ltiSignUrl = ltiSignUrl;
setStringProperty(LTI_SIGN_URL, ltiSignUrl, true);
}
public String getLtiKey() { public String getLtiKey() {
return ltiKey; return ltiKey;
} }
...@@ -177,4 +246,84 @@ public class OpencastModule extends AbstractSpringModule implements ConfigOnOff ...@@ -177,4 +246,84 @@ public class OpencastModule extends AbstractSpringModule implements ConfigOnOff
setStringProperty(LTI_SECRET, ltiSecret, true); setStringProperty(LTI_SECRET, ltiSecret, true);
} }
public boolean isBigBlueButtonEnabled() {
return enabled && bigBlueButtonEnabled;
}
public boolean isBigBlueButtonEnabledRaw() {
return bigBlueButtonEnabled;
}
public void setBigBlueButtonEnabled(boolean bigBlueButtonEnabled) {
this.bigBlueButtonEnabled = bigBlueButtonEnabled;
setStringProperty(BBB_ENABLED, Boolean.toString(bigBlueButtonEnabled), true);
}
public boolean isCourseNodeEnabled() {
return enabled && courseNodeEnabled;
}
public boolean isCourseNodeEnabledRaw() {
return courseNodeEnabled;
}
public void setCourseNodeEnabled(boolean courseNodeEnabled) {
this.courseNodeEnabled = courseNodeEnabled;
setStringProperty(COURSE_NODE_ENABLED, Boolean.toString(courseNodeEnabled), true);
}
public boolean isStartImmediately() {
return startImmediately;
}
public void setStartImmediately(boolean startImmediately) {
this.startImmediately = startImmediately;
setStringProperty(START_IMMEDIATELY, Boolean.toString(startImmediately), true);
}
public String getRolesAdmin() {
return rolesAdmin;
}
public void setRolesAdmin(String rolesAdmin) {
this.rolesAdmin = rolesAdmin;
setStringProperty(ROLES_ADMIN, rolesAdmin, true);
}
public String getRolesCoach() {
return rolesCoach;
}
public void setRolesCoach(String rolesCoach) {
this.rolesCoach = rolesCoach;
setStringProperty(ROLES_COACH, rolesCoach, true);
}
public String getRolesParticipant() {
return rolesParticipant;
}
public void setRolesParticipant(String rolesParticipant) {
this.rolesParticipant = rolesParticipant;
setStringProperty(ROLES_PARTICIPANT, rolesParticipant, true);
}
public Type getAuthDelegateType() {
return authDelegateType;
}
public void setAuthDelegateType(Type authDelegateType) {
this.authDelegateType = authDelegateType;
setStringProperty(AUTH_DELEGATE_TYPE, authDelegateType.name(), true);
}
public String getAuthDelegateRoles() {
return authDelegateRoles;
}
public void setAuthDelegateRoles(String authDelegateRoles) {
this.authDelegateRoles = authDelegateRoles;
setStringProperty(AUTH_DELEGATE_ROLES, authDelegateRoles, true);
}
} }
/**
* <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.modules.opencast;
/**
*
* Initial date: 12 Aug 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public interface OpencastSeries {
String getIdentifier();
String getTitle();
}
/**
* <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.modules.opencast;
import java.util.List;
import java.util.stream.Collectors;
import org.olat.core.CoreSpringFactory;
import org.olat.core.gui.control.generic.ajax.autocompletion.ListProvider;
import org.olat.core.gui.control.generic.ajax.autocompletion.ListReceiver;
import org.olat.core.id.Identity;
/**
*
* Initial date: 11 Aug 2020<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class OpencastSeriesProvider implements ListProvider {
private static final int LIMIT = 15;
private final String moreKey;
private final AuthDelegate authDelegate;
private List<OpencastSeries> series;
private final OpencastService opencastService;
public OpencastSeriesProvider(Identity identity, String moreKey) {
this.moreKey = moreKey;
opencastService = CoreSpringFactory.getImpl(OpencastService.class);
authDelegate = opencastService.getAuthDelegate(identity);
}
@Override
public int getMaxEntries() {
return LIMIT;
}
@Override
public void getResult(String searchValue, ListReceiver receiver) {
// Opencast does not support wildcards in filters. So we load all series
// and filter them here.
if (series == null) {
series = opencastService.getSeries(authDelegate);
}
List<OpencastSeries> matchingSeries = series.stream()
.filter(s -> s.getTitle().toLowerCase().indexOf(searchValue.toLowerCase()) > -1)
.sorted((s1, s2) -> s1.getTitle().compareToIgnoreCase(s2.getTitle()))
.collect(Collectors.toList());
List<OpencastSeries> limitedSeries = matchingSeries.stream()
.limit(LIMIT)
.collect(Collectors.toList());
limitedSeries.forEach(s -> receiver.addEntry(s.getIdentifier(), s.getTitle()));
if (matchingSeries.size() > limitedSeries.size()) {
receiver.addEntry(moreKey, moreKey);
}
}
}
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