From 23abdb52ee55589264714ea2497df4ff2c1bce3a Mon Sep 17 00:00:00 2001 From: shawn-higgins1 <23224097+shawn-higgins1@users.noreply.github.com> Date: Tue, 14 May 2019 09:01:41 -0400 Subject: [PATCH] Add paging to Recordings Table (GRN2-26) (#512) * Add translations for the validation messages * Add translations for next/prev button * Add paging to recordings * sync * Fix line endings --- app/assets/javascripts/admins.js | 40 +- app/assets/javascripts/search.js | 95 ++-- app/controllers/rooms_controller.rb | 19 +- app/controllers/users_controller.rb | 5 +- app/helpers/recordings_helper.rb | 2 + app/models/concerns/api_concern.rb | 63 ++- app/models/room.rb | 9 +- app/models/user.rb | 4 +- app/views/rooms/join.html.erb | 3 + app/views/rooms/show.html.erb | 2 +- app/views/shared/_room_event.html.erb | 2 +- app/views/shared/_sessions.html.erb | 52 ++- .../shared/components/_subtitle.html.erb | 24 +- .../shared/settings/_setting_view.html.erb | 31 +- app/views/users/recordings.html.erb | 2 +- config/initializers/pagy.rb | 2 +- spec/models/room_spec.rb | 406 +++++++++++++++++- spec/models/user_spec.rb | 93 ++++ 18 files changed, 725 insertions(+), 129 deletions(-) diff --git a/app/assets/javascripts/admins.js b/app/assets/javascripts/admins.js index 777a9385..1ceaf4c1 100644 --- a/app/assets/javascripts/admins.js +++ b/app/assets/javascripts/admins.js @@ -41,32 +41,6 @@ $(document).on('turbolinks:load', function(){ location.reload() }); }); - - // Submit search if the user hits enter - $("#search-input").keypress(function(key) { - var keyPressed = key.which - if (keyPressed == 13) { - searchPage() - } - }) - - // Add listeners for sort - $("th[data-order]").click(function(data){ - var header_elem = $(data.target) - - if(header_elem.data('order') === 'asc'){ // asc - header_elem.data('order', 'desc'); - } - else if(header_elem.data('order') === 'desc'){ // desc - header_elem.data('order', 'none'); - } - else{ // none - header_elem.data('order', 'asc'); - } - - var search = $("#search-input").val() - window.location.replace(window.location.pathname + "?page=1&search=" + search + "&column=" + header_elem.data("header") + "&direction="+ header_elem.data('order')) - }) } // Only run on the admins edit user page. @@ -76,8 +50,8 @@ $(document).on('turbolinks:load', function(){ if (!url.endsWith("/")) { url += "/" } - url += "admins?setting=" + data.target.id + window.location.href = url }) } @@ -88,15 +62,3 @@ function changeBrandingImage(path) { var url = $("#branding-url").val() $.post(path, {url: url}) } - -// Searches the user table for the given string -function searchPage() { - var search = $("#search-input").val() - - window.location.replace(window.location.pathname + "?page=1&search=" + search) -} - -// Clears the search bar -function clearSearch() { - window.location.replace(window.location.pathname + "?page=1") -} diff --git a/app/assets/javascripts/search.js b/app/assets/javascripts/search.js index 04081922..80642256 100644 --- a/app/assets/javascripts/search.js +++ b/app/assets/javascripts/search.js @@ -18,36 +18,81 @@ $(document).on('turbolinks:load', function(){ var controller = $("body").data('controller'); var action = $("body").data('action'); - if(controller == "rooms" && action == "show" || controller == "rooms" && action == "update"){ - var search_input = $('#search_bar'); + if ((controller == "admins" && action == "index") || + (controller == "rooms" && action == "show") || + (controller == "rooms" && action == "update") || + (controller == "rooms" && action == "join") || + (controller == "users" && action == "recordings")) { + // Submit search if the user hits enter + $("#search-input").keypress(function(key) { + var keyPressed = key.which + if (keyPressed == 13) { + searchPage() + } + }) - search_input.bind("keyup", function(){ + // Add listeners for sort + $("th[data-order]").click(function(data){ + var header_elem = $(data.target) + var controller = $("body").data('controller'); + var action = $("body").data('action'); - // Retrieve the current search query - var search_query = search_input.find(".form-control").val(); + if(header_elem.data('order') === 'asc'){ // asc + header_elem.data('order', 'desc'); + } + else if(header_elem.data('order') === 'desc'){ // desc + header_elem.data('order', 'none'); + } + else{ // none + header_elem.data('order', 'asc'); + } - //Search for recordings and display them based on name match - var recordings_found = 0; + var search = $("#search-input").val(); - var recordings = $('#recording-table').find('tr'); - - recordings.each(function(){ - if($(this).find('text').text().toLowerCase().includes(search_query.toLowerCase())){ - recordings_found = recordings_found + 1; - $(this).show(); - } - else{ - $(this).hide(); - } - }); - - // Show "No recordings match your search" if no recordings found - if(recordings_found === 0){ - $('#no_recordings_found').show(); + if(controller === "rooms" && action === "show"){ + window.location.replace(window.location.pathname + "?page=1&search=" + search + + "&column=" + header_elem.data("header") + "&direction="+ header_elem.data('order') + + "#recordings-table"); } else{ - $('#no_recordings_found').hide(); + window.location.replace(window.location.pathname + "?page=1&search=" + search + + "&column=" + header_elem.data("header") + "&direction="+ header_elem.data('order')); } - }); + }) + + if(controller === "rooms" && action === "show"){ + $(".page-item > a").each(function(){ + if(!$(this).attr('href').endsWith("#")){ + $(this).attr('href', $(this).attr('href') + "#recordings-table") + } + }) + } } -}); +}) + +// Searches the user table for the given string +function searchPage() { + var search = $("#search-input").val(); + + var controller = $("body").data('controller'); + var action = $("body").data('action'); + + if(controller === "rooms" && action === "show"){ + window.location.replace(window.location.pathname + "?page=1&search=" + search + "#recordings-table"); + } else{ + window.location.replace(window.location.pathname + "?page=1&search=" + search); + } + +} + +// Clears the search bar +function clearSearch() { + var controller = $("body").data('controller'); + var action = $("body").data('action'); + + if(controller === "rooms" && action === "show"){ + window.location.replace(window.location.pathname + "?page=1" + "#recordings-table"); + } else{ + window.location.replace(window.location.pathname + "?page=1"); + } +} diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index 4f0a3042..1918474d 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -18,6 +18,7 @@ class RoomsController < ApplicationController include RecordingsHelper + include Pagy::Backend before_action :validate_accepted_terms, unless: -> { !Rails.configuration.terms } before_action :validate_verified_email, except: [:show, :join], @@ -52,9 +53,11 @@ class RoomsController < ApplicationController # GET /:room_uid def show if current_user && @room.owned_by?(current_user) - recs = @room.recordings + @search, @order_column, @order_direction, recs = + @room.recordings(params.permit(:search, :column, :direction), true) + + @pagy, @recordings = pagy_array(recs) - @recordings = recs @is_running = @room.running? else # Get users name @@ -66,6 +69,11 @@ class RoomsController < ApplicationController "" end + @search, @order_column, @order_direction, pub_recs = + @room.public_recordings(params.permit(:search, :column, :direction), true) + + @pagy, @public_recordings = pagy_array(pub_recs) + render :join end end @@ -119,6 +127,13 @@ class RoomsController < ApplicationController redirect_to @room.join_path(join_name, opts) end else + + search_params = params[@room.invite_path] || params + @search, @order_column, @order_direction, pub_recs = + @room.public_recordings(search_params.permit(:search, :column, :direction), true) + + @pagy, @public_recordings = pagy_array(pub_recs) + # They need to wait until the meeting begins. render :wait end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index c10b5133..026bb3e2 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -18,6 +18,7 @@ class UsersController < ApplicationController include RecordingsHelper + include Pagy::Backend include Emailer before_action :find_user, only: [:edit, :update, :destroy] @@ -141,7 +142,9 @@ class UsersController < ApplicationController # GET /u/:user_uid/recordings def recordings if current_user && current_user.uid == params[:user_uid] - @recordings = current_user.all_recordings + @search, @order_column, @order_direction, recs = + current_user.all_recordings(params.permit(:search, :column, :direction), true) + @pagy, @recordings = pagy_array(recs) else redirect_to root_path end diff --git a/app/helpers/recordings_helper.rb b/app/helpers/recordings_helper.rb index 1775307d..e96fcd2f 100644 --- a/app/helpers/recordings_helper.rb +++ b/app/helpers/recordings_helper.rb @@ -17,6 +17,8 @@ # with BigBlueButton; if not, see . module RecordingsHelper + include Pagy::Frontend + # Helper for converting BigBlueButton dates into the desired format. def recording_date(date) date.strftime("%B #{date.day.ordinalize}, %Y.") diff --git a/app/models/concerns/api_concern.rb b/app/models/concerns/api_concern.rb index 8c46d617..dd766d25 100644 --- a/app/models/concerns/api_concern.rb +++ b/app/models/concerns/api_concern.rb @@ -19,8 +19,14 @@ module APIConcern extend ActiveSupport::Concern - # Format recordings to match their current use in the app - def format_recordings(api_res) + # Format, filter, and sort recordings to match their current use in the app + def format_recordings(api_res, search_params, ret_search_params) + search = search_params[:search] || "" + order_col = search_params[:column] && search_params[:direction] != "none" ? search_params[:column] : "end_time" + order_dir = search_params[:column] && search_params[:direction] != "none" ? search_params[:direction] : "asc" + + search = search.downcase + api_res[:recordings].each do |r| next if r.key?(:error) # Format playbacks in a more pleasant way. @@ -34,6 +40,57 @@ module APIConcern r.delete(:playback) end - api_res[:recordings].sort_by { |rec| rec[:endTime] }.reverse + recs = filter_recordings(api_res, search) + recs = sort_recordings(recs, order_col, order_dir) + + if ret_search_params + [search, order_col, order_dir, recs] + else + recs + end + end + + def filter_recordings(api_res, search) + api_res[:recordings].select do |r| + (!r[:metadata].nil? && ((!r[:metadata][:name].nil? && + r[:metadata][:name].downcase.include?(search)) || + (r[:metadata][:"gl-listed"] == "true" && search == "public") || + (r[:metadata][:"gl-listed"] == "false" && search == "unlisted"))) || + ((r[:metadata].nil? || r[:metadata][:name].nil?) && + r[:name].downcase.include?(search)) || + r[:participants].include?(search) || + !r[:playbacks].select { |p| p[:type].downcase.include?(search) }.empty? + end + end + + def sort_recordings(recs, order_col, order_dir) + recs = case order_col + when "end_time" + recs.sort_by { |r| r[:endTime] } + when "name" + recs.sort_by do |r| + if !r[:metadata].nil? && !r[:metadata][:name].nil? + r[:metadata][:name].downcase + else + r[:name].downcase + end + end + when "length" + recs.sort_by { |r| r[:playbacks].reject { |p| p[:type] == "statistics" }.first[:length] } + when "users" + recs.sort_by { |r| r[:participants] } + when "visibility" + recs.sort_by { |r| r[:metadata][:"gl-listed"] } + when "formats" + recs.sort_by { |r| r[:playbacks].first[:type].downcase } + else + recs.sort_by { |r| r[:endTime] } + end + + if order_dir == 'asc' + recs + else + recs.reverse + end end end diff --git a/app/models/room.rb b/app/models/room.rb index 5e01e2d7..dc0b5af2 100644 --- a/app/models/room.rb +++ b/app/models/room.rb @@ -121,15 +121,16 @@ class Room < ApplicationRecord end # Fetches all recordings for a room. - def recordings + def recordings(search_params = {}, ret_search_params = false) res = bbb.get_recordings(meetingID: bbb_id) - format_recordings(res) + format_recordings(res, search_params, ret_search_params) end # Fetches a rooms public recordings. - def public_recordings - recordings.select { |r| r[:metadata][:"gl-listed"] == "true" } + def public_recordings(search_params = {}, ret_search_params = false) + search, order_col, order_dir, recs = recordings(search_params, ret_search_params) + [search, order_col, order_dir, recs.select { |r| r[:metadata][:"gl-listed"] == "true" }] end def update_recording(record_id, meta) diff --git a/app/models/user.rb b/app/models/user.rb index f67026dc..8588587e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -121,7 +121,7 @@ class User < ApplicationRecord order("#{column} #{direction}") end - def all_recordings + def all_recordings(search_params = {}, ret_search_params = false) pag_num = Rails.configuration.pagination_number pag_loops = rooms.length / pag_num - 1 @@ -142,7 +142,7 @@ class User < ApplicationRecord full_res = bbb.get_recordings(meetingID: last_pag_room.pluck(:bbb_id)) res[:recordings].push(*full_res[:recordings]) - format_recordings(res) + format_recordings(res, search_params, ret_search_params) end # Activates an account and initialize a users main room diff --git a/app/views/rooms/join.html.erb b/app/views/rooms/join.html.erb index b2b3f63b..70c74c82 100644 --- a/app/views/rooms/join.html.erb +++ b/app/views/rooms/join.html.erb @@ -16,6 +16,9 @@ <%= render 'shared/room_event' do %> <%= form_for room_path(@room), method: :post do |f| %>
+ <%= f.hidden_field(:search, :value => params[:search])%> + <%= f.hidden_field(:column, :value => params[:column])%> + <%= f.hidden_field(:direction, :value => params[:direction])%> <%= f.text_field :join_name, required: true, class: "form-control join-form", diff --git a/app/views/rooms/show.html.erb b/app/views/rooms/show.html.erb index 83e1e93f..e9b76d47 100644 --- a/app/views/rooms/show.html.erb +++ b/app/views/rooms/show.html.erb @@ -86,6 +86,6 @@
-<%= render "shared/sessions", recordings: @recordings, only_public: false, user_recordings: false, title: t("room.recordings")%> +<%= render "shared/sessions", recordings: @recordings, pagy: @pagy, only_public: false, user_recordings: false, title: t("room.recordings")%> <%= render "shared/modals/create_room_modal" %> diff --git a/app/views/shared/_room_event.html.erb b/app/views/shared/_room_event.html.erb index 61e35de9..2dbcda0e 100644 --- a/app/views/shared/_room_event.html.erb +++ b/app/views/shared/_room_event.html.erb @@ -40,4 +40,4 @@ -<%= render "shared/sessions", recordings: @room.public_recordings, only_public: true, user_recordings: false, title: t("room.recordings") %> +<%= render "shared/sessions", recordings: @public_recordings, pagy: @pagy, only_public: true, user_recordings: false, title: t("room.recordings") %> diff --git a/app/views/shared/_sessions.html.erb b/app/views/shared/_sessions.html.erb index d1cf8860..2b6932c5 100644 --- a/app/views/shared/_sessions.html.erb +++ b/app/views/shared/_sessions.html.erb @@ -21,21 +21,54 @@
- +
- + <% if recording_thumbnails? %> - + <% end %> - - + + - - <% unless only_public %> <% end %> @@ -68,6 +101,11 @@ <% end %>
" data-order="none"><%= t("recording.table.name") %>"> + <%= t("recording.table.name") %> + <% if @order_column == "name" && @order_direction == "desc" %> + ↓ + <% elsif @order_column == "name" && @order_direction == "asc" %> + ↑ + <% end %> + <%= t("recording.table.thumbnails") %> + <%= t("recording.table.thumbnails") %> + " data-order="none"> + "> <%= t("recording.table.length") %> + <% if @order_column == "length" && @order_direction == "desc" %> + ↓ + <% elsif @order_column == "length" && @order_direction == "asc" %> + ↑ + <% end %> " data-order="none"> + "> <%= t("recording.table.users") %> + <% if @order_column == "users" && @order_direction == "desc" %> + ↓ + <% elsif @order_column == "users" && @order_direction == "asc" %> + ↑ + <% end %> + "> + <%= t("recording.table.visibility") %> + <% if @order_column == "visibility" && @order_direction == "desc" %> + ↓ + <% elsif @order_column == "visibility" && @order_direction == "asc" %> + ↑ + <% end %> + "> + <%= t("recording.table.formats") %> + <% if @order_column == "formats" && @order_direction == "desc" %> + ↓ + <% elsif @order_column == "formats" && @order_direction == "asc" %> + ↑ + <% end %> <%= t("recording.table.visibility") %><%= t("recording.table.formats") %>
+ <% if !recordings.empty?%> +
+ <%== pagy_bootstrap_nav(pagy) %> +
+ <% end %>
diff --git a/app/views/shared/components/_subtitle.html.erb b/app/views/shared/components/_subtitle.html.erb index b072e380..29870f89 100644 --- a/app/views/shared/components/_subtitle.html.erb +++ b/app/views/shared/components/_subtitle.html.erb @@ -18,14 +18,24 @@

<%= subtitle %>

<% if search %> -