From f042993b8b91a348430ed4e6eab3b36f792effa7 Mon Sep 17 00:00:00 2001 From: srosse <stephane.rosse@frentix.com> Date: Tue, 9 Jun 2020 16:05:49 +0200 Subject: [PATCH] OO-4734: webcam only layout option for BigBlueButton meeting --- .../bigbluebutton/BigBlueButtonMeeting.java | 4 ++ .../BigBlueButtonMeetingLayoutEnum.java | 46 +++++++++++++++ .../manager/BigBlueButtonManagerImpl.java | 14 ++++- .../manager/BigBlueButtonMeetingDAO.java | 2 + .../model/BigBlueButtonMeetingImpl.java | 28 +++++++++ .../EditBigBlueButtonMeetingController.java | 58 ++++++++++++++++++- .../ui/_i18n/LocalStrings_de.properties | 3 + .../ui/_i18n/LocalStrings_en.properties | 3 + .../database/mysql/alter_15_0_x_to_15_1_0.sql | 4 ++ .../database/mysql/setupDatabase.sql | 1 + .../oracle/alter_15_0_x_to_15_1_0.sql | 4 ++ .../database/oracle/setupDatabase.sql | 1 + .../postgresql/alter_15_0_x_to_15_1_0.sql | 4 ++ .../database/postgresql/setupDatabase.sql | 1 + 14 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonMeetingLayoutEnum.java diff --git a/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonMeeting.java b/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonMeeting.java index 0534275e6e6..48a8f07bfa7 100644 --- a/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonMeeting.java +++ b/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonMeeting.java @@ -54,6 +54,10 @@ public interface BigBlueButtonMeeting extends ModifiedInfo, CreateInfo { public void setWelcome(String welcome); + public BigBlueButtonMeetingLayoutEnum getMeetingLayout(); + + public void setMeetingLayout(BigBlueButtonMeetingLayoutEnum layout); + public boolean isPermanent(); public void setPermanent(boolean permanent); diff --git a/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonMeetingLayoutEnum.java b/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonMeetingLayoutEnum.java new file mode 100644 index 00000000000..6c7da91b254 --- /dev/null +++ b/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonMeetingLayoutEnum.java @@ -0,0 +1,46 @@ +/** + * <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.bigbluebutton; + +import org.olat.core.util.StringHelper; + +/** + * + * Initial date: 9 juin 2020<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public enum BigBlueButtonMeetingLayoutEnum { + + standard, + webcam; + + public static final BigBlueButtonMeetingLayoutEnum secureValueOf(String val) { + BigBlueButtonMeetingLayoutEnum layout = BigBlueButtonMeetingLayoutEnum.standard; + if(StringHelper.containsNonWhitespace(val)) { + for(BigBlueButtonMeetingLayoutEnum l:values()) { + if(l.name().equals(val)) { + layout = l; + } + } + } + return layout; + } +} diff --git a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java index 25d827b755d..3cca3082d0b 100644 --- a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java +++ b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java @@ -60,6 +60,7 @@ import org.olat.group.BusinessGroupService; import org.olat.group.DeletableGroupData; import org.olat.modules.bigbluebutton.BigBlueButtonManager; import org.olat.modules.bigbluebutton.BigBlueButtonMeeting; +import org.olat.modules.bigbluebutton.BigBlueButtonMeetingLayoutEnum; import org.olat.modules.bigbluebutton.BigBlueButtonMeetingTemplate; import org.olat.modules.bigbluebutton.BigBlueButtonModule; import org.olat.modules.bigbluebutton.BigBlueButtonRecording; @@ -735,12 +736,21 @@ public class BigBlueButtonManagerImpl implements BigBlueButtonManager, } BigBlueButtonUriBuilder uriBuilder = getUriBuilder(server); - return uriBuilder + uriBuilder .operation("join") .parameter("meetingID", meeting.getMeetingId()) .parameter("fullName", getFullName(identity)) .parameter("password", password) - .optionalParameter("userID", userId) + .optionalParameter("userID", userId); + + if(BigBlueButtonMeetingLayoutEnum.webcam.equals(meeting.getMeetingLayout())) { + uriBuilder + .optionalParameter("userdata-bbb_auto_swap_layout", "true") + .optionalParameter("userdata-bbb_auto_share_webcam", "true") + .optionalParameter("userdata-bbb_show_participants_on_login", "false"); + } + + return uriBuilder .build() .toString(); } diff --git a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonMeetingDAO.java b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonMeetingDAO.java index abe4aa8ac96..0e6a8ad7811 100644 --- a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonMeetingDAO.java +++ b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonMeetingDAO.java @@ -33,6 +33,7 @@ import org.olat.core.commons.persistence.QueryBuilder; import org.olat.core.util.StringHelper; import org.olat.group.BusinessGroup; import org.olat.modules.bigbluebutton.BigBlueButtonMeeting; +import org.olat.modules.bigbluebutton.BigBlueButtonMeetingLayoutEnum; import org.olat.modules.bigbluebutton.BigBlueButtonMeetingTemplate; import org.olat.modules.bigbluebutton.BigBlueButtonServer; import org.olat.modules.bigbluebutton.model.BigBlueButtonMeetingImpl; @@ -62,6 +63,7 @@ public class BigBlueButtonMeetingDAO { meeting.setMeetingId(UUID.randomUUID().toString()); meeting.setAttendeePassword(UUID.randomUUID().toString()); meeting.setModeratorPassword(UUID.randomUUID().toString()); + meeting.setMeetingLayout(BigBlueButtonMeetingLayoutEnum.standard); meeting.setEntry(entry); meeting.setSubIdent(subIdent); diff --git a/src/main/java/org/olat/modules/bigbluebutton/model/BigBlueButtonMeetingImpl.java b/src/main/java/org/olat/modules/bigbluebutton/model/BigBlueButtonMeetingImpl.java index 146482c3d05..538468e1cfd 100644 --- a/src/main/java/org/olat/modules/bigbluebutton/model/BigBlueButtonMeetingImpl.java +++ b/src/main/java/org/olat/modules/bigbluebutton/model/BigBlueButtonMeetingImpl.java @@ -37,6 +37,7 @@ import org.olat.core.id.Persistable; import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupImpl; import org.olat.modules.bigbluebutton.BigBlueButtonMeeting; +import org.olat.modules.bigbluebutton.BigBlueButtonMeetingLayoutEnum; import org.olat.modules.bigbluebutton.BigBlueButtonMeetingTemplate; import org.olat.modules.bigbluebutton.BigBlueButtonServer; import org.olat.repository.RepositoryEntry; @@ -90,6 +91,9 @@ public class BigBlueButtonMeetingImpl implements Persistable, BigBlueButtonMeeti @Column(name="b_permanent", nullable=false, insertable=true, updatable=true) private boolean permanent; + + @Column(name="b_layout", nullable=false, insertable=true, updatable=true) + private String layout; @Column(name="b_meeting_id", nullable=false, insertable=true, updatable=false) private String meetingId; @@ -200,6 +204,30 @@ public class BigBlueButtonMeetingImpl implements Persistable, BigBlueButtonMeeti public void setWelcome(String welcome) { this.welcome = welcome; } + + + + public String getLayout() { + return layout; + } + + public void setLayout(String layout) { + this.layout = layout; + } + + @Override + public BigBlueButtonMeetingLayoutEnum getMeetingLayout() { + return BigBlueButtonMeetingLayoutEnum.secureValueOf(layout); + } + + @Override + public void setMeetingLayout(BigBlueButtonMeetingLayoutEnum meetingLayout) { + if(meetingLayout == null) { + layout = BigBlueButtonMeetingLayoutEnum.standard.name(); + } else { + layout = meetingLayout.name(); + } + } @Override public boolean isPermanent() { diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonMeetingController.java b/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonMeetingController.java index baa43adcda0..e0a24061f8c 100644 --- a/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonMeetingController.java +++ b/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonMeetingController.java @@ -42,6 +42,7 @@ import org.olat.core.util.StringHelper; import org.olat.group.BusinessGroup; import org.olat.modules.bigbluebutton.BigBlueButtonManager; import org.olat.modules.bigbluebutton.BigBlueButtonMeeting; +import org.olat.modules.bigbluebutton.BigBlueButtonMeetingLayoutEnum; import org.olat.modules.bigbluebutton.BigBlueButtonMeetingTemplate; import org.olat.modules.bigbluebutton.BigBlueButtonModule; import org.olat.modules.bigbluebutton.BigBlueButtonTemplatePermissions; @@ -65,6 +66,7 @@ public class EditBigBlueButtonMeetingController extends FormBasicController { private DateChooser startDateEl; private DateChooser endDateEl; private SingleSelection templateEl; + private SingleSelection layoutEl; private final Mode mode; private final String subIdent; @@ -171,7 +173,27 @@ public class EditBigBlueButtonMeetingController extends FormBasicController { if(!templateSelected && templatesKeys.length > 0) { templateEl.select(templatesKeys[0], true); } - + + KeyValues layoutKeyValues = new KeyValues(); + layoutKeyValues.add(KeyValues.entry(BigBlueButtonMeetingLayoutEnum.standard.name(), translate("layout.standard"))); + if(isWebcamLayoutAvailable()) { + layoutKeyValues.add(KeyValues.entry(BigBlueButtonMeetingLayoutEnum.webcam.name(), translate("layout.webcam"))); + } + layoutEl = uifactory.addDropdownSingleselect("meeting.layout", "meeting.layout", formLayout, + layoutKeyValues.keys(), layoutKeyValues.values()); + boolean layoutSelected = false; + String selectedLayout = meeting == null ? BigBlueButtonMeetingLayoutEnum.standard.name() : meeting.getMeetingLayout().name(); + for(String layoutKey:layoutKeyValues.keys()) { + if(layoutKey.equals(selectedLayout)) { + layoutEl.select(layoutKey, true); + layoutSelected = true; + } + } + if(!layoutSelected) { + layoutEl.select(BigBlueButtonMeetingLayoutEnum.standard.name(), true); + } + layoutEl.setVisible(layoutEl.getKeys().length > 1); + openCalLink = uifactory.addFormLink("calendar.open", formLayout); openCalLink.setIconLeftCSS("o_icon o_icon-fw o_icon_calendar"); updateTemplateInformations(); @@ -217,6 +239,14 @@ public class EditBigBlueButtonMeetingController extends FormBasicController { } } + private boolean isWebcamLayoutAvailable() { + if(!templateEl.isOneSelected()) { + return true; + } + BigBlueButtonMeetingTemplate template = getSelectedTemplate(); + return template != null && (template.getWebcamsOnlyForModerator() == null || !template.getWebcamsOnlyForModerator().booleanValue()); + } + private void updateTemplateInformations() { templateEl.setExampleKey(null, null); if(templateEl.isOneSelected()) { @@ -234,6 +264,24 @@ public class EditBigBlueButtonMeetingController extends FormBasicController { } } + private void updateLayoutSelection() { + boolean webcamAvailable = isWebcamLayoutAvailable(); + if(webcamAvailable && layoutEl.getKeys().length == 1) { + KeyValues layoutKeyValues = new KeyValues(); + layoutKeyValues.add(KeyValues.entry(BigBlueButtonMeetingLayoutEnum.standard.name(), translate("layout.standard"))); + layoutKeyValues.add(KeyValues.entry(BigBlueButtonMeetingLayoutEnum.webcam.name(), translate("layout.webcam"))); + layoutEl.setKeysAndValues(layoutKeyValues.keys(), layoutKeyValues.values(), null); + } else if(!webcamAvailable && layoutEl.getKeys().length > 1) { + layoutEl.select(BigBlueButtonMeetingLayoutEnum.standard.name(), true); + + KeyValues layoutKeyValues = new KeyValues(); + layoutKeyValues.add(KeyValues.entry(BigBlueButtonMeetingLayoutEnum.standard.name(), translate("layout.standard"))); + layoutEl.setKeysAndValues(layoutKeyValues.keys(), layoutKeyValues.values(), null); + } + + layoutEl.setVisible(layoutEl.getKeys().length > 1); + } + private void doOpenCalendar(UserRequest ureq) { removeAsListenerAndDispose(calCtr); removeAsListenerAndDispose(cmc); @@ -428,6 +476,7 @@ public class EditBigBlueButtonMeetingController extends FormBasicController { protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { if(templateEl == source) { updateTemplateInformations(); + updateLayoutSelection(); } else if (openCalLink == source) { doOpenCalendar(ureq); } @@ -465,6 +514,13 @@ public class EditBigBlueButtonMeetingController extends FormBasicController { meeting.setFollowupTime(followupTime); } + if(layoutEl.isVisible() && layoutEl.isOneSelected()) { + BigBlueButtonMeetingLayoutEnum layout = BigBlueButtonMeetingLayoutEnum.secureValueOf(layoutEl.getSelectedKey()); + meeting.setMeetingLayout(layout); + } else { + meeting.setMeetingLayout(BigBlueButtonMeetingLayoutEnum.standard); + } + bigBlueButtonManager.updateMeeting(meeting); fireEvent(ureq, Event.DONE_EVENT); diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties index c7c2064e0a3..c7e1d7a82a7 100644 --- a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties @@ -56,6 +56,8 @@ error.too.long.time=Zeit ist zu lang. Es sind maximal {0} Minuten erlaubt. error.url.invalid=Ung\u00FCltige Serveradresse filter.all.instances=Alle OpenOlats filter.this.instance=Dieses OpenOlat +layout.standard=Standard +layout.webcam=Webcam Termin meeting.create.intro=Der Online-Termin wurde vom Betreuer noch nicht er\u00F6ffnet. Teilnehmer k\u00F6nnen den Raum noch nicht betreten. meeting.day=Datum des Meetings meeting.deleted=Das Meeting wurde erfolgreich gel\u00F6scht. @@ -65,6 +67,7 @@ meeting.ended=Der Online-Termin wurde bereits beendet. meeting.followupTime=Nachlaufzeit (Min.) meeting.go.button=Zum Online-Termin Raum meeting.join.button=Meeting beitreten +meeting.layout=Darstellung meeting.leadTime=Vorlaufzeit (Min.) meeting.leadTime.explain=Die Vorlaufzeit ist nur f\u00FCr Moderatoren relevant. meeting.name=Name diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_en.properties index 048640dc3bf..dbb087ec630 100644 --- a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_en.properties @@ -56,6 +56,8 @@ error.too.long.time=Time is too long. It is limited to {0} minutes. error.url.invalid=Invalid server URL filter.all.instances=All OpenOlats filter.this.instance=This OpenOlat +layout.standard=Standard +layout.webcam=Webcam meeting meeting.create.intro=The meeting has not yet been started by the coach. Participants are not able to enter the classroom. meeting.day=Date of the meeting meeting.deleted=The meeting was successfully deleted. @@ -65,6 +67,7 @@ meeting.ended=The online-meeting has already ended. meeting.followupTime=Follow-up (min.) meeting.go.button=Go to the onlin-meeting room meeting.join.button=Join the meeting +meeting.layout=Layout meeting.leadTime=Prep time (min.) meeting.leadTime.explain=Prep time is only relevant for moderators. meeting.name=Name diff --git a/src/main/resources/database/mysql/alter_15_0_x_to_15_1_0.sql b/src/main/resources/database/mysql/alter_15_0_x_to_15_1_0.sql index 6a7674dc2cc..6398b3f4d96 100644 --- a/src/main/resources/database/mysql/alter_15_0_x_to_15_1_0.sql +++ b/src/main/resources/database/mysql/alter_15_0_x_to_15_1_0.sql @@ -4,6 +4,10 @@ alter table o_bs_identity add column inactivationemaildate datetime; alter table o_bs_identity add column deletionemaildate datetime; +-- BigBlueButton +alter table o_bbb_meeting add column b_layout varchar(16) default 'standard'; + + -- Appointments create table o_ap_topic ( id bigint not null auto_increment, diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql index b982291c057..fdf1d8bcba3 100644 --- a/src/main/resources/database/mysql/setupDatabase.sql +++ b/src/main/resources/database/mysql/setupDatabase.sql @@ -1204,6 +1204,7 @@ create table o_bbb_meeting ( b_name varchar(128) not null, b_description varchar(2000) default null, b_welcome mediumtext, + b_layout varchar(16) default 'standard', b_permanent bool default false not null, b_start_date datetime default null, b_leadtime bigint default 0 not null, diff --git a/src/main/resources/database/oracle/alter_15_0_x_to_15_1_0.sql b/src/main/resources/database/oracle/alter_15_0_x_to_15_1_0.sql index 262344bd5be..d4f33987e8c 100644 --- a/src/main/resources/database/oracle/alter_15_0_x_to_15_1_0.sql +++ b/src/main/resources/database/oracle/alter_15_0_x_to_15_1_0.sql @@ -4,6 +4,10 @@ alter table o_bs_identity add inactivationemaildate date; alter table o_bs_identity add deletionemaildate date; +-- BigBlueButton +alter table o_bbb_meeting add b_layout varchar2(16) default 'standard'; + + -- Appointments create table o_ap_topic ( id number(20) generated always as identity, diff --git a/src/main/resources/database/oracle/setupDatabase.sql b/src/main/resources/database/oracle/setupDatabase.sql index 71a69295b52..4af0597b96e 100644 --- a/src/main/resources/database/oracle/setupDatabase.sql +++ b/src/main/resources/database/oracle/setupDatabase.sql @@ -1267,6 +1267,7 @@ create table o_bbb_meeting ( b_name varchar(128) not null, b_description varchar(2000) default null, b_welcome CLOB, + b_layout varchar2(16) default 'standard', b_permanent number default 0 not null, b_start_date timestamp default null, b_leadtime number(20) default 0 not null, diff --git a/src/main/resources/database/postgresql/alter_15_0_x_to_15_1_0.sql b/src/main/resources/database/postgresql/alter_15_0_x_to_15_1_0.sql index fbcdb8fd1b6..57add3c0a5f 100644 --- a/src/main/resources/database/postgresql/alter_15_0_x_to_15_1_0.sql +++ b/src/main/resources/database/postgresql/alter_15_0_x_to_15_1_0.sql @@ -4,6 +4,10 @@ alter table o_bs_identity add column inactivationemaildate timestamp; alter table o_bs_identity add column deletionemaildate timestamp; +-- BigBlueButton +alter table o_bbb_meeting add column b_layout varchar(16) default 'standard'; + + -- Appointments create table o_ap_topic ( id bigserial, diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql index fddc7eff2aa..a4ea3b26c7d 100644 --- a/src/main/resources/database/postgresql/setupDatabase.sql +++ b/src/main/resources/database/postgresql/setupDatabase.sql @@ -1226,6 +1226,7 @@ create table o_bbb_meeting ( b_name varchar(128) not null, b_description varchar(2000) default null, b_welcome text, + b_layout varchar(16) default 'standard', b_permanent bool default false not null, b_start_date timestamp default null, b_leadtime bigint default 0 not null, -- GitLab