* set up video route

* add video index

* update styling

* fix mobile full width styling

* bust cache when new video is created

* add unlimited scrolling
This commit is contained in:
Jess Lee 2019-04-05 14:02:03 -04:00 committed by Ben Halpern
parent b98565a931
commit 175569fb97
8 changed files with 190 additions and 4 deletions

View file

@ -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 '<a class="single-video-article single-article" href="'+video_article.path+'" id="video-article-'+video_article.id+'">\
<img src="'+video_article.cloudinary_video_url+'">\
<p><strong>'+video_article.title+'</strong></p>\
<p>'+video_article.user.name+'</p>\
<span class="video-timestamp">'+video_article.video_duration_in_minutes+'</span></a>';
}
function fetchNextPodcastPage(el){
var indexParams = JSON.parse(el.dataset.params);
var urlParams = Object.keys(indexParams).map(function(k) {

View file

@ -29,6 +29,7 @@
@import 'tag-edit';
@import 'sticky-nav';
@import 'sidebar-data';
@import 'video-collection';
@import 'ltags/LiquidTags';

View file

@ -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%;
}
}
}
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,19 @@
<div class="home video-page-title" id="index-container" data-which="videos" data-params="<%= params.to_json(only: %i[tag username q]) %>">
<header>
<h1>Videos</h1>
</header>
<div class="video-collection" id="video-collection">
<% @video_articles.each do |video_article| %>
<a class="single-video-article single-article" href="<%= video_article.path %>" id="video-article-<%= video_article.id %>">
<img src="<%= video_article.cloudinary_video_url %>">
<p><strong><%= video_article.title %></strong></p>
<p><%= User.find(video_article.user_id).name %></p>
<span class="video-timestamp"><%= video_article.video_duration_in_minutes %></span>
</a>
<% end %>
</div>
<div class="subvideos"></div>
<div class="loading-articles" id="loading-articles">
loading...
</div>
</div>

View file

@ -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