diff --git a/app/assets/javascripts/channels/recording_update.js b/app/assets/javascripts/channels/recording_update.js index 500dee66..1b13b5bb 100644 --- a/app/assets/javascripts/channels/recording_update.js +++ b/app/assets/javascripts/channels/recording_update.js @@ -23,17 +23,21 @@ }, { received: function(data) { + var recordings = Recordings.getInstance(); - var table = recordings.table.api() + var table = recordings.table.api(); var row = table.row("#"+data.record_id); + if (data.action === 'update') { var rowData = row.data(); - rowData.published = data.published + + rowData.published = data.published; + rowData.listed = data.listed; table.row("#"+data.record_id).data(rowData); recordings.draw(); - var published = (data.published) ? 'published' : 'unpublished'; - showAlert(I18n['recording_'+published], 4000); + var status = data.published ? (data.listed ? 'published' : 'unlisted') : 'unpublished'; + showAlert(I18n['recording_'+status], 4000); } else if (data.action === 'delete') { row.remove(); recordings.draw(); diff --git a/app/assets/javascripts/landing.js b/app/assets/javascripts/landing.js index cac4e377..da819eb0 100644 --- a/app/assets/javascripts/landing.js +++ b/app/assets/javascripts/landing.js @@ -100,7 +100,8 @@ .tooltip('fixTitle'); }); - $('.center-panel-wrapper').on ('click', '.meeting-invite', function (event) { + // button used to send invitations to the meeting (i.e. "mailto:" link) + $('.center-panel-wrapper').on('click', '.meeting-invite', function (event) { var meetingURL = Meeting.getInstance().getURL(); var subject = $(this).data("invite-subject"); var body = $(this).data("invite-body").replace("&&URL&&", meetingURL); diff --git a/app/assets/javascripts/recordings.coffee b/app/assets/javascripts/recordings.coffee index 00abec2f..d6ee8d3d 100644 --- a/app/assets/javascripts/recordings.coffee +++ b/app/assets/javascripts/recordings.coffee @@ -37,7 +37,7 @@ class @Recordings { data: "previews", orderable: false }, { data: "duration", orderable: false }, { data: "playbacks", orderable: false }, - { data: "published", visible: false }, + { data: "listed", visible: false }, { data: "id", orderable: false } ], columnDefs: [ @@ -78,18 +78,18 @@ class @Recordings render: (data, type, row) -> if type == 'display' roomName = Meeting.getInstance().getId() - published = row.published - publishText = if published then 'unpublish' else 'publish' recordingActions = $('.hidden-elements').find('.recording-actions') - recordingActions.find('.recording-update > i.default') - .removeClass(PUBLISHED_CLASSES.join(' ')) - .addClass(getPublishClass(published)) - recordingActions.find('.recording-update > i.hover') - .removeClass(PUBLISHED_CLASSES.join(' ')) - .addClass(getPublishClass(!published)) - recordingActions.find('.recording-update') - .attr('data-published', published) - .attr('title', I18n[publishText+'_recording']) + classes = ['recording-inaccessible', 'recording-unlisted', 'recording-published'] + if row.published + if row.listed + cls = classes[2] + else + cls = classes[1] + else + cls = classes[0] + trigger = recordingActions.find('.recording-update-trigger') + trigger.removeClass(classes.join(' ')) + trigger.addClass(cls) return recordingActions.html() return data } @@ -111,9 +111,10 @@ class @Recordings html: true, trigger: 'focus', title: -> - return I18n.are_you_sure; + return $(this).data("popover-title"); content: -> - return $(".delete-popover-body").html() + bodySelector = $(this).data("popover-body") + return $(bodySelector).html() } $('#recordings').popover(options) @@ -153,17 +154,25 @@ class @Recordings # setup click handlers for the action buttons setupActionHandlers: -> table_api = this.table.api() + @getTable().on 'click', '.recording-update', (event) -> btn = $(this) row = table_api.row($(this).closest('tr')).data() url = $('.meeting-url').val() id = row.id - published = btn.data('published') + + published = btn.data('visibility') == "unlisted" || + btn.data('visibility') == "published" + listed = btn.data('visibility') == "published" + btn.prop('disabled', true) $.ajax({ method: 'PATCH', url: url+'/recordings/'+id, - data: {published: (!published).toString()} + data: { + published: published.toString(), + "meta_greenlight-listed": listed.toString() + } }).done((data) -> ).fail((data) -> diff --git a/app/assets/javascripts/shared.js b/app/assets/javascripts/shared.js index 52553d87..854679a5 100644 --- a/app/assets/javascripts/shared.js +++ b/app/assets/javascripts/shared.js @@ -20,12 +20,6 @@ $.ajaxSetup({ } }); -var PUBLISHED_CLASSES = ['fa-eye-slash', 'fa-eye'] - -var getPublishClass = function(published) { - return PUBLISHED_CLASSES[+published]; -} - var loopJoin = function() { var jqxhr = Meeting.getInstance().getJoinMeetingResponse(); jqxhr.done(function(data) { @@ -57,4 +51,4 @@ var showAlert = function(html, timeout_delay) { var displayRoomURL = function() { $('.meeting-url').val(Meeting.getInstance().getURL()); -} +}; diff --git a/app/assets/stylesheets/landing.scss b/app/assets/stylesheets/landing.scss index d0cbee70..172dbec2 100644 --- a/app/assets/stylesheets/landing.scss +++ b/app/assets/stylesheets/landing.scss @@ -86,3 +86,17 @@ } } } + +.recording-update-trigger { + &.recording-inaccessible { + color: red; + } + + &.recording-unlisted { + color: #e3a91e; + } + + &.recording-published { + color: green; + } +} diff --git a/app/assets/stylesheets/shared.scss b/app/assets/stylesheets/shared.scss index b11c4df6..7dbbb0da 100644 --- a/app/assets/stylesheets/shared.scss +++ b/app/assets/stylesheets/shared.scss @@ -106,3 +106,7 @@ html, body { text-align: center; } } + +.popover { + max-width: none; +} diff --git a/app/controllers/bbb_controller.rb b/app/controllers/bbb_controller.rb index 84fff310..ae2272a7 100644 --- a/app/controllers/bbb_controller.rb +++ b/app/controllers/bbb_controller.rb @@ -76,9 +76,11 @@ class BbbController < ApplicationController # PATCH /rooms/:id/recordings/:record_id def update_recordings - bbb_res = bbb_update_recordings(params[:record_id], params[:published] == 'true') + published = params[:published] == 'true' + metadata = params.select{ |k, v| k.match(/^meta_/) } + bbb_res = bbb_update_recordings(params[:record_id], published, metadata) if bbb_res[:returncode] - RecordingUpdatesJob.perform_later(@user.encrypted_id, params[:record_id], bbb_res[:published]) + RecordingUpdatesJob.perform_later(@user.encrypted_id, params[:record_id]) end render_bbb_response bbb_res end diff --git a/app/jobs/recording_updates_job.rb b/app/jobs/recording_updates_job.rb index 5b9903ea..6c21a6f0 100644 --- a/app/jobs/recording_updates_job.rb +++ b/app/jobs/recording_updates_job.rb @@ -19,22 +19,13 @@ class RecordingUpdatesJob < ApplicationJob queue_as :default - def perform(room, record_id, published) - tries = 0 - sleep_time = 2 - - while tries < 4 - bbb_res = bbb_get_recordings(nil, record_id) - if bbb_res[:recordings].first[:published].to_s == published - ActionCable.server.broadcast "#{room}_recording_updates_channel", - action: 'update', - record_id: record_id, - published: bbb_res[:recordings].first[:published] - break - end - sleep sleep_time - sleep_time = sleep_time * 2 - tries += 1 - end + def perform(room, record_id) + bbb_res = bbb_get_recordings(nil, record_id) + recording = bbb_res[:recordings].first + ActionCable.server.broadcast "#{room}_recording_updates_channel", + action: 'update', + record_id: record_id, + published: recording[:published], + listed: bbb_is_recording_listed(recording) end end diff --git a/app/lib/bbb_api.rb b/app/lib/bbb_api.rb index 090a0f3d..a12657fb 100644 --- a/app/lib/bbb_api.rb +++ b/app/lib/bbb_api.rb @@ -15,6 +15,8 @@ # with BigBlueButton; if not, see . module BbbApi + META_LISTED = "greenlight-listed" + def bbb_endpoint Rails.configuration.bigbluebutton_endpoint || '' end @@ -65,7 +67,14 @@ module BbbApi logout_url = options[:meeting_logout_url] || "#{request.base_url}" moderator_password = random_password(12) viewer_password = random_password(12) - meeting_options = {record: options[:meeting_recorded].to_s, logoutURL: logout_url, moderatorPW: moderator_password, attendeePW: viewer_password} + meeting_options = { + record: options[:meeting_recorded].to_s, + logoutURL: logout_url, + moderatorPW: moderator_password, + attendeePW: viewer_password, + "meta_#{BbbApi::META_LISTED}": false + } + # Create the meeting bbb.create_meeting(options[:meeting_name], meeting_id, meeting_options) @@ -148,6 +157,8 @@ module BbbApi else [] end + + recording[:listed] = bbb_is_recording_listed(recording) end res end @@ -168,8 +179,11 @@ module BbbApi response_data = bbb_exception_res exc end - def bbb_update_recordings(id, published) + def bbb_update_recordings(id, published, metadata) bbb_safe_execute :publish_recordings, id, published + + params = { recordID: id }.merge(metadata) + bbb_safe_execute :send_api_request, "updateRecordings", params end def bbb_delete_recordings(id) @@ -191,6 +205,11 @@ module BbbApi response_data end + def bbb_is_recording_listed(recording) + !recording[:metadata].blank? && + recording[:metadata][BbbApi::META_LISTED.to_sym] == "true" + end + def success_join_res(join_url) { returncode: true, diff --git a/app/views/bbb/recordings.jbuilder b/app/views/bbb/recordings.jbuilder index e1174e8b..b7f7d7cc 100644 --- a/app/views/bbb/recordings.jbuilder +++ b/app/views/bbb/recordings.jbuilder @@ -24,6 +24,7 @@ json.recordings do json.end_time recording[:endTime] json.published recording[:published] json.length recording[:length] + json.listed recording[:listed] json.previews do json.array!(recording[:previews]) do |preview| json.partial! 'preview', preview: preview diff --git a/app/views/landing/rooms.html.erb b/app/views/landing/rooms.html.erb index aa350b17..f42270dd 100644 --- a/app/views/landing/rooms.html.erb +++ b/app/views/landing/rooms.html.erb @@ -50,6 +50,17 @@ with BigBlueButton; if not, see . <%= t('no') %> +
+ + + +
diff --git a/config/locales/en-us.yml b/config/locales/en-us.yml index 9789b312..b44ff5f5 100644 --- a/config/locales/en-us.yml +++ b/config/locales/en-us.yml @@ -38,6 +38,8 @@ en-US: actions: Actions are_you: Are you %{name}? + are_you_sure: Are you sure? + change_recording_visibility: "Change visibility to:" client: are_you_sure: Are you sure? delete_recording: Delete recording @@ -48,6 +50,7 @@ en-US: publish_recording: Publish recording recording_deleted: Recording was deleted recording_published: Recording was published + recording_unlisted: Recording was unlisted recording_unpublished: Recording was unpublished unpublish_recording: Hide recording copied: Copied @@ -61,6 +64,7 @@ en-US: greet_user: Welcome, %{name} greet_guest: Welcome to %{name} Meeting Space hi_all: Hi Everyone + innaccessible: Innaccessible join: Join join_session: Join the current session join_session_id: Join %{id} @@ -82,11 +86,13 @@ en-US: footer_html: "%{greenlight_link} build %{version}, Powered by %{bbb_link}" presentation: Presentation previously_joined_meetings: Previously Joined Sessions + published: Published return_to_room: Return to your personal room session_url_explanation: The session will be taking place using the following URL start: Start your_personal_room: Your Personal Room thumbnails: Thumbnails + unlisted: Unlisted url_copy_explanation: Copy this URL to invite others to the meeting url_refresh_hint: Generate a new meeting URL video: Video