forked from External/greenlight
improvements to active meetings
This commit is contained in:
parent
44e2cb7027
commit
27f6076954
|
@ -18,6 +18,7 @@
|
|||
// the landing page using custom Actioncable events.
|
||||
|
||||
var MEETINGS = {}
|
||||
var WAITING = {}
|
||||
var LOADING_DELAY = 1750 // milliseconds.
|
||||
|
||||
var updatePreviousMeetings = function(){
|
||||
|
@ -29,19 +30,44 @@ var updatePreviousMeetings = function(){
|
|||
});
|
||||
}
|
||||
|
||||
var handleUser = function(data, n){
|
||||
var addUser = function(data){
|
||||
if(data['role'] == 'MODERATOR'){
|
||||
MEETINGS[data['meeting']]['moderators'] += n
|
||||
MEETINGS[data['meeting']]['moderators'].push(data['user'])
|
||||
} else {
|
||||
MEETINGS[data['meeting']]['participants'] += n
|
||||
MEETINGS[data['meeting']]['participants'].push(data['user'])
|
||||
}
|
||||
updateMeetingText(MEETINGS[data['meeting']])
|
||||
}
|
||||
|
||||
var updateMeetingText = function(meeting){
|
||||
$('#' + meeting['name'].replace(' ', '_')).html('<a>' + meeting['name'] + '</a> <i>(' +
|
||||
meeting['participants'] + ((meeting['participants'] == 1) ? ' user, ' : ' users, ') +
|
||||
meeting['moderators'] + ((meeting['moderators'] == 1) ? ' mod)' : ' mods)'))
|
||||
var removeUser = function(data){
|
||||
if(data['role'] == 'MODERATOR'){
|
||||
MEETINGS[data['meeting']]['moderators'].splice(MEETINGS[data['meeting']]['moderators'].indexOf(data['user']), 1);
|
||||
} else {
|
||||
MEETINGS[data['meeting']]['participants'].splice(MEETINGS[data['meeting']]['participants'].indexOf(data['user']), 1);
|
||||
}
|
||||
updateMeetingText(MEETINGS[data['meeting']])
|
||||
}
|
||||
|
||||
var updateMeetingText = function(m){
|
||||
if(m.hasOwnProperty('moderators')){
|
||||
var body = '<a>' + m['name'] + '</a><i>: ' + m['moderators'].join('(mod), ') + (m['moderators'].length > 0 ? '(mod)' : '') +
|
||||
(m['participants'].length > 0 && m['moderators'].length != 0 ? ', ' : '') + m['participants'].join(', ') + '</i>'
|
||||
} else {
|
||||
var body = '<a>' + m['name'] + '</a><i> (not yet started): ' +
|
||||
m['users'].join(', ') + '</i>'
|
||||
}
|
||||
|
||||
if($('#' + m['name'].replace(' ', '_')).length == 0){
|
||||
var meeting_item = $('<li id = ' + m['name'].replace(' ', '_') + '>' + body + '</li>')
|
||||
$('.actives').append(meeting_item);
|
||||
|
||||
// Set up join on click.
|
||||
meeting_item.click(function(){
|
||||
joinMeeting(m['name']);
|
||||
});
|
||||
} else {
|
||||
$('#' + m['name'].replace(' ', '_')).html(body)
|
||||
}
|
||||
}
|
||||
|
||||
var initialPopulate = function(){
|
||||
|
@ -49,21 +75,48 @@ var initialPopulate = function(){
|
|||
var chopped = window.location.href.split('/')
|
||||
if (!window.location.href.includes('rooms') || chopped[chopped.length - 2] == $('body').data('current-user')) { return; }
|
||||
$.get((window.location.href + '/request').replace('#', ''), function(data){
|
||||
var meetings = data['meetings']
|
||||
var meetings = data['active']['meetings']
|
||||
var waiting = data['waiting']
|
||||
|
||||
jQuery.each(waiting[$('body').data('current-user')], function(name, users){
|
||||
WAITING[name] = {'name': name,
|
||||
'users': users}
|
||||
updateMeetingText(WAITING[name])
|
||||
});
|
||||
|
||||
for(var i = 0; i < meetings.length; i++){
|
||||
// Make sure the meeting actually belongs to the current user.
|
||||
if(meetings[i]['metadata']['room-id'] != $('body').data('current-user')) { continue; }
|
||||
var name = meetings[i]['meetingName']
|
||||
var participants = parseInt(meetings[i]['participantCount'])
|
||||
var moderators = parseInt(meetings[i]['moderatorCount'])
|
||||
|
||||
var participants = []
|
||||
var moderators = []
|
||||
|
||||
var attendees;
|
||||
if(meetings[i]['attendees']['attendee'] instanceof Array){
|
||||
attendees = meetings[i]['attendees']['attendee']
|
||||
} else {
|
||||
attendees = [meetings[i]['attendees']['attendee']]
|
||||
}
|
||||
|
||||
jQuery.each(attendees, function(i, attendee){
|
||||
if(attendee['role'] == "MODERATOR"){
|
||||
moderators.push(attendee['fullName'])
|
||||
} else {
|
||||
participants.push(attendee['fullName'])
|
||||
}
|
||||
});
|
||||
|
||||
// Create meeting.
|
||||
MEETINGS[name] = {'name': name,
|
||||
'participants': participants - moderators,
|
||||
'participants': participants,
|
||||
'moderators': moderators}
|
||||
|
||||
if(isPreviouslyJoined(name)){
|
||||
renderActiveMeeting(MEETINGS[name])
|
||||
updateMeetingText(MEETINGS[name])
|
||||
}
|
||||
}
|
||||
|
||||
}).done(function(){
|
||||
// Remove from previous meetings if they are active.
|
||||
updatePreviousMeetings();
|
||||
|
@ -81,18 +134,6 @@ var isPreviouslyJoined = function(meeting){
|
|||
return joinedMeetings.split(',').indexOf(meeting) >= 0
|
||||
}
|
||||
|
||||
var renderActiveMeeting = function(m){
|
||||
var meeting_item = $('<li id = ' + m['name'].replace(' ', '_') + '><a>' + m['name'] + '</a>' +
|
||||
' <i>(' + m['participants'] + ((m['participants'] == 1) ? ' user, ' : ' users, ') +
|
||||
m['moderators'] + ((m['moderators'] == 1) ? ' mod)' : ' mods)') + '</i>' + '</li>')
|
||||
$('.actives').append(meeting_item);
|
||||
|
||||
// Set up join on click.
|
||||
meeting_item.click(function(){
|
||||
joinMeeting(m['name']);
|
||||
});
|
||||
}
|
||||
|
||||
var removeActiveMeeting = function(meeting){
|
||||
if(meeting){
|
||||
$('#' + meeting['name'].replace(' ', '_')).remove()
|
||||
|
@ -137,20 +178,36 @@ $(document).on('turbolinks:load', function(){
|
|||
if(data['method'] == 'create'){
|
||||
// Create an empty meeting.
|
||||
MEETINGS[data['meeting']] = {'name': data['meeting'],
|
||||
'participants': 0,
|
||||
'moderators': 0}
|
||||
|
||||
renderActiveMeeting(MEETINGS[data['meeting']])
|
||||
'participants': [],
|
||||
'moderators': []}
|
||||
updateMeetingText(MEETINGS[data['meeting']])
|
||||
updatePreviousMeetings();
|
||||
if (WAITING.hasOwnProperty(data['meeting'])){ delete WAITING[data['meeting']]; }
|
||||
} else if(data['method'] == 'destroy'){
|
||||
removeActiveMeeting(MEETINGS[data['meeting']])
|
||||
PreviousMeetings.uniqueAdd([data['meeting']])
|
||||
delete MEETINGS[data['meeting']]
|
||||
} else if(data['method'] == 'join'){
|
||||
handleUser(data, 1)
|
||||
updateMeetingText(MEETINGS[data['meeting']])
|
||||
addUser(data)
|
||||
} else if(data['method'] == 'leave'){
|
||||
handleUser(data, -1)
|
||||
removeUser(data)
|
||||
} else if(data['method'] == 'waiting'){
|
||||
// Handle waiting meeting.
|
||||
if(WAITING.hasOwnProperty(data['meeting'])){
|
||||
WAITING[data['meeting']]['users'].push(data['user'])
|
||||
updateMeetingText(WAITING[data['meeting']])
|
||||
} else {
|
||||
WAITING[data['meeting']] = {'name': data['meeting'],
|
||||
'users': [data['user']]}
|
||||
updateMeetingText(WAITING[data['meeting']])
|
||||
}
|
||||
} else if((data['method'] == 'no_longer_waiting') && (WAITING.hasOwnProperty(data['meeting']))){
|
||||
WAITING[data['meeting']]['users'].splice(WAITING[data['meeting']]['users'].indexOf(data['user']), 1)
|
||||
updateMeetingText(WAITING[data['meeting']])
|
||||
if(WAITING[data['meeting']]['users'].length == 0){
|
||||
removeActiveMeeting(WAITING[data['meeting']])
|
||||
delete WAITING[data['meeting']]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
(function() {
|
||||
|
||||
var waitForModerator = function(url) {
|
||||
$.get(url + "/wait", function(html) {
|
||||
localStorage.setItem("waitingName", $('.meeting-user-name').val());
|
||||
$.post(url + "/wait", {name: $('.meeting-user-name').val()}, function(html) {
|
||||
$(".center-panel-wrapper").html(html);
|
||||
});
|
||||
if (!Meeting.getInstance().getWaitingForMod()) {
|
||||
|
|
|
@ -287,14 +287,17 @@ class BbbController < ApplicationController
|
|||
actioncable_event('create', params['id'], params['room_id'])
|
||||
elsif eventName == "meeting_destroyed_event"
|
||||
actioncable_event('destroy', params['id'], params['room_id'])
|
||||
|
||||
record_id = event['payload']['meeting_id'].split('-')[0]
|
||||
rec_info = bbb_get_recordings({recordID: record_id})
|
||||
rec_info = rec_info[:recordings].first
|
||||
|
||||
# Remove the webhook.
|
||||
webhook_remove(rec_info[:metadata][:"gl-webhooks-callback-url"])
|
||||
elsif eventName == "user_joined_message"
|
||||
actioncable_event('join', params['id'], params['room_id'], event['payload']['user']['role'])
|
||||
actioncable_event('join', params['id'], params['room_id'], event['payload']['user']['name'], event['payload']['user']['role'])
|
||||
elsif eventName == "user_left_message"
|
||||
actioncable_event('leave', params['id'], params['room_id'], event['payload']['user']['role'])
|
||||
actioncable_event('leave', params['id'], params['room_id'], event['payload']['user']['name'], event['payload']['user']['role'])
|
||||
else
|
||||
logger.info "Callback event will not be treated. Event name: #{eventName}"
|
||||
end
|
||||
|
@ -302,11 +305,12 @@ class BbbController < ApplicationController
|
|||
render head(:ok) && return
|
||||
end
|
||||
|
||||
def actioncable_event(method, id, room_id, role = 'none')
|
||||
def actioncable_event(method, id, room_id, user = 'none', role = 'none')
|
||||
ActionCable.server.broadcast 'refresh_meetings',
|
||||
method: method,
|
||||
meeting: id,
|
||||
room: room_id,
|
||||
user: user,
|
||||
role: role
|
||||
end
|
||||
|
||||
|
|
|
@ -34,14 +34,29 @@ class LandingController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def send_data
|
||||
render json: bbb.get_meetings
|
||||
def send_meetings_data
|
||||
render json: {active: bbb.get_meetings, waiting: WaitingList.waiting}
|
||||
end
|
||||
|
||||
def wait_for_moderator
|
||||
WaitingList.add(params[:room_id], params[:name], params[:id])
|
||||
ActionCable.server.broadcast 'refresh_meetings',
|
||||
method: 'waiting',
|
||||
meeting: params[:id],
|
||||
room: params[:room_id],
|
||||
user: params[:name]
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def no_longer_waiting
|
||||
WaitingList.remove(params[:room_id], params[:name], params[:id])
|
||||
ActionCable.server.broadcast 'refresh_meetings',
|
||||
method: 'no_longer_waiting',
|
||||
meeting: params[:id],
|
||||
room: params[:room_id],
|
||||
user: params[:name]
|
||||
end
|
||||
|
||||
def session_status_refresh
|
||||
@user = User.find_by(encrypted_id: params[:room_id])
|
||||
if @user.nil?
|
||||
|
|
|
@ -100,6 +100,8 @@ module BbbApi
|
|||
rescue BigBlueButton::BigBlueButtonException => exc
|
||||
logger.info "BBB error on create #{exc.key}: #{exc.message}"
|
||||
end
|
||||
|
||||
WaitingList.empty(options[:room_owner], options[:meeting_name])
|
||||
|
||||
# And then get meeting info
|
||||
bbb_meeting_info = bbb.get_meeting_info( meeting_id, nil )
|
||||
|
|
|
@ -28,3 +28,11 @@
|
|||
<%= image_tag "loading-indicator.gif", :alt => "" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<script>
|
||||
// Notify the server when a user is no longer waiting to join a meeting.
|
||||
|
||||
window.addEventListener("beforeunload", function(e){
|
||||
$.post(window.location.href + '/no_longer_wait', {name: localStorage.waitingName});
|
||||
}, false);
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# Stores data on waiting users on the server side so
|
||||
# we can pass it to clients when they reload the page.
|
||||
|
||||
class WaitingList
|
||||
@waiting = {}
|
||||
|
||||
def self.waiting
|
||||
@waiting
|
||||
end
|
||||
|
||||
def self.add(room, user, meeting)
|
||||
@waiting[room] = {} unless @waiting.has_key?(room)
|
||||
@waiting[room][meeting] = [] unless @waiting[room].has_key?(meeting)
|
||||
@waiting[room][meeting] << user
|
||||
end
|
||||
|
||||
def self.remove(room, user, meeting)
|
||||
if @waiting.has_key?(room) then
|
||||
if @waiting[room].has_key?(meeting) then
|
||||
@waiting[room][meeting].slice!(@waiting[room][meeting].index(user))
|
||||
@waiting[room].delete(meeting) if @waiting[room][meeting].length == 0
|
||||
@waiting.delete(room) if @waiting[room].length == 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.empty(room, meeting)
|
||||
if @waiting.has_key?(room) then
|
||||
if @waiting[room].has_key?(meeting) then
|
||||
@waiting[room].delete(meeting)
|
||||
@waiting.delete(room) if @waiting[room].length == 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -44,13 +44,14 @@ Rails.application.routes.draw do
|
|||
delete '/(:id)/recordings/:record_id', to: 'bbb#delete_recordings', defaults: {id: nil, format: 'json'}, :constraints => {:id => disallow_slash}
|
||||
|
||||
delete '/:id/end', to: 'bbb#end', defaults: {format: 'json'}, :constraints => {:id => disallow_slash}
|
||||
get '/:id/wait', to: 'landing#wait_for_moderator', :constraints => {:id => disallow_slash}
|
||||
post '/:id/wait', to: 'landing#wait_for_moderator', :constraints => {:id => disallow_slash}
|
||||
post '/:id/no_longer_wait', to: 'landing#no_longer_waiting', :constraints => {:id => disallow_slash}
|
||||
get '/:id/session_status_refresh', to: 'landing#session_status_refresh', :constraints => {:id => disallow_slash}
|
||||
end
|
||||
post '/:room_id/:id/callback', to: 'bbb#callback', :constraints => {:id => disallow_slash, :room_id => disallow_slash}
|
||||
|
||||
# routes shared between meetings and rooms
|
||||
get '/(:room_id)/request', to: 'landing#send_data', :defaults => { :format => 'xml' }
|
||||
get '/(:room_id)/request', to: 'landing#send_meetings_data', :defaults => { :format => 'xml' }
|
||||
get '/(:room_id)/:id/join', to: 'bbb#join', defaults: {room_id: nil, format: 'json'}, :constraints => {:id => disallow_slash, :room_id => disallow_slash}
|
||||
get '/(:room_id)/:id', to: 'landing#resource', as: :meeting_room, defaults: {room_id: nil}, :constraints => {:id => disallow_slash, :room_id => disallow_slash}
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue