From 3c18c4f4b686b70eba60b06915eb69a588c374c9 Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Wed, 24 Feb 2021 10:26:01 +0100
Subject: [PATCH] OO-5308: allow to generate invitee url for BigBLueButton in
 wizard

---
 .../ui/AppointmentEditController.java         |  6 ++-
 .../ui/RecurringAppointmentsController.java   |  4 +-
 .../ui/TopicCreateController.java             |  4 +-
 .../BigBlueButtonEditMeetingsController.java  | 12 ++++++
 .../ui/BigBlueButtonUIHelper.java             | 12 ++++--
 .../EditBigBlueButtonMeetingController.java   | 11 ++++--
 .../ui/_i18n/LocalStrings_de.properties       |  1 +
 .../ui/_i18n/LocalStrings_en.properties       |  1 +
 ...gButtonMeetingConfigurationController.java | 39 +++++++++++++++++++
 .../recurring/RecurringMeetingsContext.java   | 18 +++++++++
 10 files changed, 95 insertions(+), 13 deletions(-)

diff --git a/src/main/java/org/olat/modules/appointments/ui/AppointmentEditController.java b/src/main/java/org/olat/modules/appointments/ui/AppointmentEditController.java
index 1f5cce10f78..58e82b067fb 100644
--- a/src/main/java/org/olat/modules/appointments/ui/AppointmentEditController.java
+++ b/src/main/java/org/olat/modules/appointments/ui/AppointmentEditController.java
@@ -242,7 +242,8 @@ public class AppointmentEditController extends FormBasicController {
 			
 			openCalLink = uifactory.addFormLink("calendar.open", formLayout);
 			openCalLink.setIconLeftCSS("o_icon o_icon-fw o_icon_calendar");
-			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, null, null, null, recordEl, templates);
+			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, null, null, null, recordEl,
+					templates, meeting != null && meeting.getKey() != null);
 			
 			String leadtime = meeting == null ? null : Long.toString(meeting.getLeadTime());
 			leadTimeEl = uifactory.addTextElement("meeting.leadTime", 8, leadtime, formLayout);
@@ -305,7 +306,8 @@ public class AppointmentEditController extends FormBasicController {
 		} else if (source == bbbRoomEl) {
 			updateUI();
 		} else if (templateEl == source) {
-			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, null, null, null, recordEl, templates);
+			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, null, null, null, recordEl,
+					templates, meeting != null && meeting.getKey() != null);
 			boolean webcamAvailable = isWebcamLayoutAvailable(getSelectedTemplate(templateEl, templates));
 			BigBlueButtonUIHelper.updateLayoutSelection(layoutEl, getTranslator(), webcamAvailable);
 		} else if (openCalLink == source) {
diff --git a/src/main/java/org/olat/modules/appointments/ui/RecurringAppointmentsController.java b/src/main/java/org/olat/modules/appointments/ui/RecurringAppointmentsController.java
index 892c23c2b54..fdf711973df 100644
--- a/src/main/java/org/olat/modules/appointments/ui/RecurringAppointmentsController.java
+++ b/src/main/java/org/olat/modules/appointments/ui/RecurringAppointmentsController.java
@@ -180,7 +180,7 @@ public class RecurringAppointmentsController extends FormBasicController {
 			
 			openCalLink = uifactory.addFormLink("calendar.open", formLayout);
 			openCalLink.setIconLeftCSS("o_icon o_icon-fw o_icon_calendar");
-			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, null, null, null, recordEl, templates);
+			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, null, null, null, recordEl, templates, false);
 			
 			leadTimeEl = uifactory.addTextElement("meeting.leadTime", 8, null, formLayout);
 			leadTimeEl.setExampleKey("meeting.leadTime.explain", null);
@@ -235,7 +235,7 @@ public class RecurringAppointmentsController extends FormBasicController {
 		if (source == bbbRoomEl) {
 			updateUI();
 		} else if (templateEl == source) {
-			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, null, null, null, recordEl, templates);
+			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, null, null, null, recordEl, templates, false);
 			boolean webcamAvailable = isWebcamLayoutAvailable(getSelectedTemplate(templateEl, templates));
 			BigBlueButtonUIHelper.updateLayoutSelection(layoutEl, getTranslator(), webcamAvailable);
 		} else if (openCalLink == source) {
diff --git a/src/main/java/org/olat/modules/appointments/ui/TopicCreateController.java b/src/main/java/org/olat/modules/appointments/ui/TopicCreateController.java
index 63848b7f67e..0ea50b06a76 100644
--- a/src/main/java/org/olat/modules/appointments/ui/TopicCreateController.java
+++ b/src/main/java/org/olat/modules/appointments/ui/TopicCreateController.java
@@ -274,7 +274,7 @@ public class TopicCreateController extends FormBasicController {
 			
 			openCalLink = uifactory.addFormLink("calendar.open", formLayout);
 			openCalLink.setIconLeftCSS("o_icon o_icon-fw o_icon_calendar");
-			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, null, null, null, recordEl, templates);
+			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, null, null, null, recordEl, templates, false);
 			
 			leadTimeEl = uifactory.addTextElement("meeting.leadTime", 8, null, formLayout);
 			leadTimeEl.setExampleKey("meeting.leadTime.explain", null);
@@ -356,7 +356,7 @@ public class TopicCreateController extends FormBasicController {
 		} else if (source == bbbRoomEl) {
 			updateUI();
 		} else if (templateEl == source) {
-			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, null, null, null, recordEl, templates);
+			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, null, null, null, recordEl, templates, false);
 			boolean webcamAvailable = isWebcamLayoutAvailable(getSelectedTemplate(templateEl, templates));
 			BigBlueButtonUIHelper.updateLayoutSelection(layoutEl, getTranslator(), webcamAvailable);
 		} else if (openCalLink == source) {
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonEditMeetingsController.java b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonEditMeetingsController.java
index f6c5f96cba6..646778f4362 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonEditMeetingsController.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonEditMeetingsController.java
@@ -50,6 +50,7 @@ import org.olat.core.gui.control.generic.modal.DialogBoxController;
 import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
 import org.olat.core.gui.control.generic.wizard.StepRunnerCallback;
 import org.olat.core.gui.control.generic.wizard.StepsMainRunController;
+import org.olat.core.util.CodeHelper;
 import org.olat.core.util.StringHelper;
 import org.olat.group.BusinessGroup;
 import org.olat.modules.bigbluebutton.BigBlueButtonManager;
@@ -343,6 +344,9 @@ public class BigBlueButtonEditMeetingsController extends FormBasicController {
 	}
 	
 	private void addRecurringMeetings(RecurringMeetingsContext context) {
+		boolean generateUrl = context.getTemplate() != null && context.getTemplate().isExternalUsersAllowed() && context.isGenerateUrl();
+		boolean setPassword = generateUrl && StringHelper.containsNonWhitespace(context.getPassword());
+				
 		for(RecurringMeeting meeting:context.getMeetings()) {
 			if(meeting.isDeleted() || !meeting.isSlotAvailable()) {
 				continue;
@@ -359,6 +363,14 @@ public class BigBlueButtonEditMeetingsController extends FormBasicController {
 			bMeeting.setEndDate(meeting.getEndDate());
 			bMeeting.setLeadTime(context.getLeadTime());
 			bMeeting.setFollowupTime(context.getFollowupTime());
+			if(generateUrl) {
+				String externalLink = String.valueOf(CodeHelper.getForeverUniqueID());
+				bMeeting.setReadableIdentifier(externalLink);
+				if(setPassword) {
+					bMeeting.setPassword(context.getPassword());
+				}
+			}
+			
 			bigBlueButtonManager.updateMeeting(bMeeting);
 		}
 	}
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonUIHelper.java b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonUIHelper.java
index 40131d9f061..75d96d73e53 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonUIHelper.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonUIHelper.java
@@ -50,7 +50,7 @@ public class BigBlueButtonUIHelper {
 	
 	public static void updateTemplateInformations(SingleSelection templateEl, TextElement externalLinkEl,
 			MultipleSelectionElement passwordEnableEl, TextElement passwordEl,
-			SingleSelection publishingEl, SingleSelection recordEl, List<BigBlueButtonMeetingTemplate> templates) {
+			SingleSelection publishingEl, SingleSelection recordEl, List<BigBlueButtonMeetingTemplate> templates, boolean meetingExists) {
 		templateEl.setExampleKey(null, null);
 		if(templateEl.isOneSelected()) {
 			BigBlueButtonMeetingTemplate template = getSelectedTemplate(templateEl, templates);
@@ -66,8 +66,14 @@ public class BigBlueButtonUIHelper {
 			}
 			boolean visible = template != null && template.isExternalUsersAllowed();
 			externalLinkEl.setVisible(visible);
-			if(visible && !StringHelper.containsNonWhitespace(externalLinkEl.getValue())) {
-				externalLinkEl.setValue(Long.toString(CodeHelper.getForeverUniqueID()));
+			if(visible && !meetingExists && !StringHelper.containsNonWhitespace(externalLinkEl.getValue())) {
+				String externalLink = Long.toString(CodeHelper.getForeverUniqueID());
+				externalLinkEl.setValue(externalLink);
+				if (externalLink != null) {
+					String url = BigBlueButtonDispatcher.getMeetingUrl(externalLink);
+					externalLinkEl.setExampleKey("noTransOnlyParam", new String[] { url });	
+					externalLinkEl.showExample(true);
+				}
 			}
 			
 			if(passwordEnableEl != null) {
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 c791c72dcb3..94505385806 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonMeetingController.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonMeetingController.java
@@ -349,7 +349,7 @@ public class EditBigBlueButtonMeetingController extends FormBasicController {
 		externalLinkEl.setHelpTextKey("meeting.external.users.help", null);
 		externalLinkEl.addActionListener(FormEvent.ONCHANGE);
 		if (externalLink != null) {
-			externalLinkEl.setExampleKey("noTransOnlyParam", new String[] {BigBlueButtonDispatcher.getMeetingUrl(externalLink)});			
+			externalLinkEl.setExampleKey("noTransOnlyParam", new String[] {BigBlueButtonDispatcher.getMeetingUrl(externalLink)});
 		}
 
 		String password = meeting == null ? null : meeting.getPassword();
@@ -362,7 +362,8 @@ public class EditBigBlueButtonMeetingController extends FormBasicController {
 		
 		openCalLink = uifactory.addFormLink("calendar.open", formLayout);
 		openCalLink.setIconLeftCSS("o_icon o_icon-fw o_icon_calendar");
-		BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, passwordEnableEl, passwordEl, publishingEl, recordEl, templates);
+		BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, passwordEnableEl, passwordEl, publishingEl, recordEl,
+				templates, meeting != null && meeting.getKey() != null);
 		
 		if(mode == Mode.dates) {
 			Date startDate = meeting == null ? new Date() : meeting.getStartDate();
@@ -610,11 +611,13 @@ public class EditBigBlueButtonMeetingController extends FormBasicController {
 	@Override
 	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
 		if(templateEl == source) {
-			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, passwordEnableEl, passwordEl, publishingEl, recordEl, templates);
+			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, passwordEnableEl, passwordEl, publishingEl, recordEl,
+					templates, meeting != null && meeting.getKey() != null);
 			boolean webcamAvailable = isWebcamLayoutAvailable(getSelectedTemplate(templateEl, templates));
 			BigBlueButtonUIHelper.updateLayoutSelection(layoutEl, getTranslator(), webcamAvailable);
 		} else if(recordEl == source || passwordEnableEl == source) {
-			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, passwordEnableEl, passwordEl, publishingEl, recordEl, templates);
+			BigBlueButtonUIHelper.updateTemplateInformations(templateEl, externalLinkEl, passwordEnableEl, passwordEl, publishingEl, recordEl,
+					templates, meeting != null && meeting.getKey() != null);
 		} else if (openCalLink == source) {
 			doOpenCalendar(ureq);
 		} else if (externalLinkEl == source) {
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 95bd9357f7f..8edcea7ada5 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
@@ -42,6 +42,7 @@ connection.successful=BigBlueButton API Login erfolgreich\!
 edit.server=Server "{0}" bearbeiten
 edit.template=Raumvorlage "{0}" bearbeiten
 enable.adhoc.meeting=Adhoc Online-Termin
+enable.generate.url=URL generieren
 enable.permanent.meeting=Online-Termine ohne Datum
 error.capacity.factory=Ein Nummer zwischen 1.0 und 100.0
 error.connectionValidationFailed=Die Verbindungspr\u00fcfung ist fehlgeschlagen\: <pre>{0}</pre>
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 dd5e813c930..332278f625a 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
@@ -42,6 +42,7 @@ connection.successful=BigBlueButton API login successful\!
 edit.server=Edit server "{0}"
 edit.template=Edit room-template "{0}"
 enable.adhoc.meeting=Adhoc online-meeting
+enable.generate.url=generate URL
 enable.permanent.meeting=Online-Meetings without date
 error.capacity.factory=A number between 1.0 and 100.0
 error.connectionValidationFailed=The connection validation failed\: <pre>{0}</pre>
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/recurring/BigBlugButtonMeetingConfigurationController.java b/src/main/java/org/olat/modules/bigbluebutton/ui/recurring/BigBlugButtonMeetingConfigurationController.java
index 62c6a78b32a..2ce3c028ed1 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/recurring/BigBlugButtonMeetingConfigurationController.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/recurring/BigBlugButtonMeetingConfigurationController.java
@@ -27,6 +27,7 @@ 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.DateChooser;
+import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
 import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.Form;
@@ -51,6 +52,8 @@ import org.springframework.beans.factory.annotation.Autowired;
  *
  */
 public class BigBlugButtonMeetingConfigurationController extends StepFormBasicController {
+
+	private static final String[] onKeys = new String[] { "on" };
 	
 	private TextElement nameEl;
 	private TextElement descriptionEl;
@@ -58,6 +61,9 @@ public class BigBlugButtonMeetingConfigurationController extends StepFormBasicCo
 	private TextElement welcomeEl;
 	private TextElement leadTimeEl;
 	private TextElement followupTimeEl;
+	private MultipleSelectionElement externalLinkEl;
+	private MultipleSelectionElement passwordEnableEl;
+	private TextElement passwordEl;
 	private DateChooser startTimeEl;
 	private DateChooser endTimeEl;
 	private DateChooser endRecurringDateEl;
@@ -126,6 +132,17 @@ public class BigBlugButtonMeetingConfigurationController extends StepFormBasicCo
 		if(!templateSelected && templatesKeys.length > 0) {
 			templateEl.select(templatesKeys[0], true);
 		}
+		
+		String[] externalLinkValues = new String[] { translate("enable.generate.url") };
+		externalLinkEl = uifactory.addCheckboxesHorizontal("meeting.external.users", formLayout, onKeys, externalLinkValues);
+		externalLinkEl.addActionListener(FormEvent.ONCHANGE);
+		
+		String[] enableValues = new String[] { translate("meeting.password.enable.on") };
+		passwordEnableEl = uifactory.addCheckboxesHorizontal("meeting.password.enable", "meeting.password.enable", formLayout, onKeys, enableValues);
+		passwordEnableEl.addActionListener(FormEvent.ONCHANGE);
+		
+		passwordEl = uifactory.addTextElement("meeting.password", 64, "", formLayout);
+		
 		updateTemplateInformations();
 		
 		startRecurringDateEl = uifactory.addDateChooser("meeting.recurring.start", "meeting.recurring.start", null, formLayout);
@@ -172,10 +189,20 @@ public class BigBlugButtonMeetingConfigurationController extends StepFormBasicCo
 				} else {
 					templateEl.setExampleKey("template.explain.max.participants", args);
 				}
+				
+				externalLinkEl.setVisible(template.isExternalUsersAllowed());
+				passwordEnableEl.setVisible(template.isExternalUsersAllowed() && externalLinkEl.isAtLeastSelected(1));
+				passwordEl.setVisible(template.isExternalUsersAllowed() && passwordEnableEl.isAtLeastSelected(1));
 			}
 		}
 	}
 	
+	private void updatePasswordElement() {
+		boolean externalInkenabled = externalLinkEl.isVisible() && externalLinkEl.isAtLeastSelected(1);
+		passwordEnableEl.setVisible(externalInkenabled);
+		passwordEl.setVisible(externalInkenabled && passwordEnableEl.isAtLeastSelected(1));
+	}
+	
 	@Override
 	protected void doDispose() {
 		//
@@ -328,6 +355,8 @@ public class BigBlugButtonMeetingConfigurationController extends StepFormBasicCo
 	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
 		if(templateEl == source) {
 			updateTemplateInformations();
+		} else if(externalLinkEl == source || passwordEnableEl == source) {
+			updatePasswordElement();
 		}
 		super.formInnerEvent(ureq, source, event);
 	}
@@ -350,6 +379,16 @@ public class BigBlugButtonMeetingConfigurationController extends StepFormBasicCo
 		long followupTime = getFollowupTime();
 		meetingsContext.setFollowupTime(followupTime);
 		
+		if(externalLinkEl.isVisible() && externalLinkEl.isAtLeastSelected(1)) {
+			meetingsContext.setGenerateUrl(true);
+			if(passwordEnableEl.isAtLeastSelected(1)) {
+				meetingsContext.setPassword(passwordEl.getValue());
+			}
+		} else {
+			meetingsContext.setGenerateUrl(false);
+			meetingsContext.setPassword(null);
+		}
+		
 		meetingsContext.setStartRecurringDate(startRecurringDateEl.getDate());
 		meetingsContext.setEndRecurringDate(endRecurringDateEl.getDate());
 		
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/recurring/RecurringMeetingsContext.java b/src/main/java/org/olat/modules/bigbluebutton/ui/recurring/RecurringMeetingsContext.java
index 80c88b99144..70aa8cf645f 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/recurring/RecurringMeetingsContext.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/recurring/RecurringMeetingsContext.java
@@ -48,6 +48,8 @@ public class RecurringMeetingsContext {
 	private long followupTime;
 	private Date startRecurringDate;
 	private Date endRecurringDate;
+	private String password;
+	private boolean generateUrl;
 	private BigBlueButtonMeetingTemplate template;
 	
 	private List<RecurringMeeting> meetings = new ArrayList<>();
@@ -119,6 +121,22 @@ public class RecurringMeetingsContext {
 		this.mainPresenter = mainPresenter;
 	}
 
+	public String getPassword() {
+		return password;
+	}
+
+	public void setPassword(String password) {
+		this.password = password;
+	}
+
+	public boolean isGenerateUrl() {
+		return generateUrl;
+	}
+
+	public void setGenerateUrl(boolean generateUrl) {
+		this.generateUrl = generateUrl;
+	}
+
 	public Date getStartTime() {
 		return startTime;
 	}
-- 
GitLab