diff --git a/app/assets/javascripts/initializers/initScrolling.js.erb b/app/assets/javascripts/initializers/initScrolling.js.erb index 0c5d4f4ae..463dedf7a 100644 --- a/app/assets/javascripts/initializers/initScrolling.js.erb +++ b/app/assets/javascripts/initializers/initScrolling.js.erb @@ -4,11 +4,11 @@ function initScrolling() { function checkIfNearBottomOfPage() { var elCheck = document.getElementById("index-container"); - + if (elCheck) { var publicSearchKey = '<%= ALGOLIASEARCH_PUBLIC_SEARCH_ONLY_KEY %>' client = algoliasearch('<%= ApplicationConfig["ALGOLIASEARCH_APPLICATION_ID"] %>', publicSearchKey); - + initScrolling.called = true; if (document.getElementsByClassName("single-article").length < 2 || location.search.indexOf("q=") > -1 ) { document.getElementById("loading-articles").style.display = "none" @@ -34,12 +34,74 @@ function fetchNextPageIfNearBottom() { var indexWhich = el.dataset.which; if (indexWhich == "podcast-episodes") { fetchNextPodcastPage(el); + } else if (indexWhich == "videos") { + fetchNextVideoPage(el) } else { algoliaPaginate(el.dataset.algoliaTag); } } } +function fetchNextVideoPage(el){ + var indexParams = JSON.parse(el.dataset.params); + var urlParams = Object.keys(indexParams).map(function(k) { + return encodeURIComponent(k) + '=' + encodeURIComponent(indexParams[k]) + }).join('&'); + if (urlParams.indexOf("q=") > -1 ) { + return; + } + var endpoint = '/api/videos' + var fetchUrl = (endpoint+'?page='+nextPage+"&"+urlParams+"&signature="+parseInt(Date.now()/400000)).replace("&&","&") + window.fetch(fetchUrl) + .then(function(response) { + response.json().then(function(video_articles) { + nextPage += 1; + insertVideos(video_articles); + if (video_articles.length == 0) { + document.getElementById("loading-articles").style.display = "none" + done = true; + } + }); + }).catch(function(err) { + console.log(err); + }); +} + +function insertVideos(video_articles) { + var list = document.getElementById("subvideos"); + var newVideosHTML = ""; + video_articles.forEach(function(video_article){ + var existingEl = document.getElementById("video-article-"+video_article.id); + if(!existingEl) { + console.log('existing') + var newHTML = buildVideoArticleHTML(video_article) + newVideosHTML += newHTML + console.log(newHTML) + } + }); + + var distanceFromBottom = document.documentElement.scrollHeight - document.body.scrollTop; + var newNode = document.createElement("div"); + newNode.innerHTML = newVideosHTML; + newNode.className += "video-collection" + var singleArticles = document.getElementsByClassName("single-article"); + var lastElement = singleArticles[singleArticles.length - 1]; + insertAfter(newNode, lastElement); + console.log(nextPage) + if (nextPage > 0) { + fetching = false; + } +} + +function buildVideoArticleHTML(video_article) { + return '\ + \ +

'+video_article.title+'

\ +

'+video_article.user.name+'

\ + '+video_article.video_duration_in_minutes+'
'; +} + + function fetchNextPodcastPage(el){ var indexParams = JSON.parse(el.dataset.params); var urlParams = Object.keys(indexParams).map(function(k) { diff --git a/app/assets/stylesheets/minimal.scss b/app/assets/stylesheets/minimal.scss index 24c63a9ed..c2137dd22 100644 --- a/app/assets/stylesheets/minimal.scss +++ b/app/assets/stylesheets/minimal.scss @@ -29,6 +29,7 @@ @import 'tag-edit'; @import 'sticky-nav'; @import 'sidebar-data'; +@import 'video-collection'; @import 'ltags/LiquidTags'; diff --git a/app/assets/stylesheets/video-collection.scss b/app/assets/stylesheets/video-collection.scss new file mode 100644 index 000000000..ce2d0004c --- /dev/null +++ b/app/assets/stylesheets/video-collection.scss @@ -0,0 +1,61 @@ +@import 'variables'; + +.home.video-page-title { + margin: 68px auto 10px; + text-align: center; + background: $white; + background: var(--theme-container-background, #fff); + header { + font-size:calc(1vw + 10px); + } +} +.video-collection { + background: $white; + background: var(--theme-container-background, #fff); + display: flex; + max-width: 100%; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-evenly; + text-align: left; + @media screen and (min-width: 950px) { + border-radius: 3px; + } + + .single-video-article { + border: solid 1px $medium-gray; + margin: 5px; + max-width: 350px; + @media screen and (max-width: 739px) { + min-width: 100%; + } + .video-timestamp { + position: relative; + font-size: .8em; + top: -88px; + left: 82%; + background-color: $black; + color: $white; + padding: 3px; + } + img { + margin-bottom: 5px; + } + p { + margin: 0px; + padding: 2px 8px; + max-height: 100%; + max-width: 90%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + color: $black; + } + img { + max-width: 350px; + @media screen and (max-width: 739px) { + min-width: 100%; + } + } + } +} diff --git a/app/controllers/api/v0/videos_controller.rb b/app/controllers/api/v0/videos_controller.rb new file mode 100644 index 000000000..a223a5068 --- /dev/null +++ b/app/controllers/api/v0/videos_controller.rb @@ -0,0 +1,23 @@ +module Api + module V0 + class VideosController < ApiController + caches_action :index, + cache_path: proc { |c| c.params.permit! }, + expires_in: 10.minutes + respond_to :json + + caches_action :show, + cache_path: proc { |c| c.params.permit! }, + expires_in: 10.minutes + respond_to :json + + before_action :cors_preflight_check + after_action :cors_set_access_control_headers + + def index + @page = params[:page] + @video_articles = Article.where.not(video: nil, video_thumbnail_url: nil).where(published: true).order("published_at DESC").page(params[:page].to_i).per(24) + end + end + end +end diff --git a/app/controllers/videos_controller.rb b/app/controllers/videos_controller.rb index dc5e2feb5..692750e6d 100644 --- a/app/controllers/videos_controller.rb +++ b/app/controllers/videos_controller.rb @@ -1,13 +1,19 @@ class VideosController < ApplicationController - after_action :verify_authorized + after_action :verify_authorized, except: %i[index] + before_action :set_cache_control_headers def new authorize :video end + def index + @video_articles = Article.where.not(video: nil, video_thumbnail_url: nil).where(published: true).order("published_at DESC").page(params[:page].to_i).per(12) + end + def create authorize :video @article = ArticleWithVideoCreationService.new(article_params, current_user).create! + CacheBuster.new.bust "/videos" render action: "js_response" end diff --git a/app/views/api/v0/videos/index.json.jbuilder b/app/views/api/v0/videos/index.json.jbuilder new file mode 100644 index 000000000..5a92998ea --- /dev/null +++ b/app/views/api/v0/videos/index.json.jbuilder @@ -0,0 +1,13 @@ +json.array! @video_articles do |video_article| + json.type_of "video_article" + json.id video_article.id + json.path video_article.path + json.cloudinary_video_url video_article.cloudinary_video_url + json.title video_article.title + json.user_id video_article.user_id + json.video_duration_in_minutes video_article.video_duration_in_minutes + + json.user do + json.name video_article.user.name + end +end diff --git a/app/views/videos/index.html.erb b/app/views/videos/index.html.erb new file mode 100644 index 000000000..e232212fa --- /dev/null +++ b/app/views/videos/index.html.erb @@ -0,0 +1,19 @@ +
+
+

Videos

+
+
+ <% @video_articles.each do |video_article| %> + + +

<%= video_article.title %>

+

<%= User.find(video_article.user_id).name %>

+ <%= video_article.video_duration_in_minutes %> +
+ <% end %> +
+
+
+ loading... +
+
diff --git a/config/routes.rb b/config/routes.rb index 323bc6e90..6161dcfb6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -67,6 +67,7 @@ Rails.application.routes.draw do end end resources :comments + resources :videos, only: [:index] resources :podcast_episodes, only: [:index] resources :reactions, only: [:create] do collection do @@ -127,7 +128,7 @@ Rails.application.routes.draw do resources :buffered_articles, only: [:index] resources :events, only: %i[index show] resources :additional_content_boxes, only: [:index] - resources :videos, only: %i[create new] + resources :videos, only: %i[index create new] resources :video_states, only: [:create] resources :twilio_tokens, only: [:show] resources :html_variants