"/videos" (#2291)
* 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:
parent
b98565a931
commit
175569fb97
8 changed files with 190 additions and 4 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
@import 'tag-edit';
|
||||
@import 'sticky-nav';
|
||||
@import 'sidebar-data';
|
||||
@import 'video-collection';
|
||||
|
||||
@import 'ltags/LiquidTags';
|
||||
|
||||
|
|
|
|||
61
app/assets/stylesheets/video-collection.scss
Normal file
61
app/assets/stylesheets/video-collection.scss
Normal 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%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
app/controllers/api/v0/videos_controller.rb
Normal file
23
app/controllers/api/v0/videos_controller.rb
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
13
app/views/api/v0/videos/index.json.jbuilder
Normal file
13
app/views/api/v0/videos/index.json.jbuilder
Normal 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
|
||||
19
app/views/videos/index.html.erb
Normal file
19
app/views/videos/index.html.erb
Normal 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>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue