Commit 3d9e25b0 authored by Rafael Reggiani Manzo's avatar Rafael Reggiani Manzo

Merge branch 'player' into 'master'

Player

This MR adds the player page with the minimum css to display the video and count views.

See merge request !22
parents 2d6beb84 7c061c7d
Pipeline #3686023 passed with stage
in 11 minutes and 58 seconds
......@@ -71,6 +71,9 @@ gem 'zencoder'
# Job queue adapter for Application Job
gem 'delayed_job_active_record'
# Adds videojs v5.4.6 javascript asset
gem 'videojs_rails', git: 'https://github.com/marcheing/videojs_rails', branch: 'master'
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platform: :mri
......
GIT
remote: https://github.com/marcheing/videojs_rails
revision: e177123d0edeb683a8d0123f8fe4459e61e47797
branch: master
specs:
videojs_rails (5.4.6)
GIT
remote: https://github.com/marcheing/zencoder-fetcher.git
revision: b2cc853ceb5923e88963a8af73201b0373abcf76
......@@ -340,6 +347,7 @@ DEPENDENCIES
turbolinks (~> 5.x)
tzinfo-data
uglifier (>= 1.3.0)
videojs_rails!
web-console
zencoder
zencoder-fetcher!
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="64px" height="64px" viewBox="5.5 -3.5 64 64" enable-background="new 5.5 -3.5 64 64" xml:space="preserve">
<g>
<circle fill="#FFFFFF" cx="37.785" cy="28.501" r="28.836"/>
<path d="M37.441-3.5c8.951,0,16.572,3.125,22.857,9.372c3.008,3.009,5.295,6.448,6.857,10.314
c1.561,3.867,2.344,7.971,2.344,12.314c0,4.381-0.773,8.486-2.314,12.313c-1.543,3.828-3.82,7.21-6.828,10.143
c-3.123,3.085-6.666,5.448-10.629,7.086c-3.961,1.638-8.057,2.457-12.285,2.457s-8.276-0.808-12.143-2.429
c-3.866-1.618-7.333-3.961-10.4-7.027c-3.067-3.066-5.4-6.524-7-10.372S5.5,32.767,5.5,28.5c0-4.229,0.809-8.295,2.428-12.2
c1.619-3.905,3.972-7.4,7.057-10.486C21.08-0.394,28.565-3.5,37.441-3.5z M37.557,2.272c-7.314,0-13.467,2.553-18.458,7.657
c-2.515,2.553-4.448,5.419-5.8,8.6c-1.354,3.181-2.029,6.505-2.029,9.972c0,3.429,0.675,6.734,2.029,9.913
c1.353,3.183,3.285,6.021,5.8,8.516c2.514,2.496,5.351,4.399,8.515,5.715c3.161,1.314,6.476,1.971,9.943,1.971
c3.428,0,6.75-0.665,9.973-1.999c3.219-1.335,6.121-3.257,8.713-5.771c4.99-4.876,7.484-10.99,7.484-18.344
c0-3.543-0.648-6.895-1.943-10.057c-1.293-3.162-3.18-5.98-5.654-8.458C50.984,4.844,44.795,2.272,37.557,2.272z M37.156,23.187
l-4.287,2.229c-0.458-0.951-1.019-1.619-1.685-2c-0.667-0.38-1.286-0.571-1.858-0.571c-2.856,0-4.286,1.885-4.286,5.657
c0,1.714,0.362,3.084,1.085,4.113c0.724,1.029,1.791,1.544,3.201,1.544c1.867,0,3.181-0.915,3.944-2.743l3.942,2
c-0.838,1.563-2,2.791-3.486,3.686c-1.484,0.896-3.123,1.343-4.914,1.343c-2.857,0-5.163-0.875-6.915-2.629
c-1.752-1.752-2.628-4.19-2.628-7.313c0-3.048,0.886-5.466,2.657-7.257c1.771-1.79,4.009-2.686,6.715-2.686
C32.604,18.558,35.441,20.101,37.156,23.187z M55.613,23.187l-4.229,2.229c-0.457-0.951-1.02-1.619-1.686-2
c-0.668-0.38-1.307-0.571-1.914-0.571c-2.857,0-4.287,1.885-4.287,5.657c0,1.714,0.363,3.084,1.086,4.113
c0.723,1.029,1.789,1.544,3.201,1.544c1.865,0,3.18-0.915,3.941-2.743l4,2c-0.875,1.563-2.057,2.791-3.541,3.686
c-1.486,0.896-3.105,1.343-4.857,1.343c-2.896,0-5.209-0.875-6.941-2.629c-1.736-1.752-2.602-4.19-2.602-7.313
c0-3.048,0.885-5.466,2.658-7.257c1.77-1.79,4.008-2.686,6.713-2.686C51.117,18.558,53.938,20.101,55.613,23.187z"/>
</g>
</svg>
......@@ -15,5 +15,6 @@
#= require foundation
#= require turbolinks
#= require colorbox-rails
#= require video
$(-> $(document).foundation())
.content-detailed-section {
@include is-container;
.autoplay-section {
@include grid-col-row;
margin-bottom: 20px;
.autoplay-label {
color: $brand-gray-medium;
display: inline-block;
float: left;
font-family: $primary-font;
font-size: 16px;
font-weight: bold;
line-height: 24px;
padding-right: 8px;
}
.switch.tiny {
display: inline;
}
}
.callout {
border-left: none;
border-right: none;
border-top: none;
padding-top: 0;
}
.content-box {
@include grid-col-row;
position: relative;
text-align: center;
img {
width: 100%;
}
}
.gifplayer {
max-height: 641.25px;
}
.player-box {
width: 100%;
}
.map-player-box {
position: relative;
text-align: center;
height: 270px;
width: 480px;
.gifplayer, .video-js {
max-height: 270px;
}
}
.video-js {
height: auto !important;
width: 100%;
max-height: 641.25px;
padding-top: 56.25%;
.vjs-big-play-button {
$big-play-width: 60px;
$big-play-height: 60px;
line-height: ($big-play-width * 0.9);
height: $big-play-height;
width: $big-play-width;
left: 50%;
top: 50%;
margin-left: -($big-play-width / 2);
margin-top: -($big-play-height / 2);
/* IE8 - has no alpha support */
background-color: $brand-red;
/* Opacity: 1.0 = 100%, 0.0 = 0% */
background-color: rgba($brand-red, 0.7);
border: 4px solid #fff;
border-radius: 50%;
}
&:hover .vjs-big-play-button,
.vjs-big-play-button:focus {
background-color: rgba($brand-red-hover, 0.7);
}
.vjs-control {
&:focus:before,
&:hover:before,
&:focus {
background-color: rgba($brand-red, 0.7);
}
}
.vjs-slider {
background-color: $brand-gray-medium;
background-color: rgba($brand-gray-medium, 0.5);
}
.vjs-play-progress,
.vjs-volume-level,
.vjs-slider-bar {
background-color: $brand-red;
}
.vjs-load-progress {
/* For IE8 we'll lighten the color */
background: ligthen($brand-gray-medium, 25%);
/* Otherwise we'll rely on stacked opacities */
background: rgba($brand-gray-medium, 0.5);
div {
/* For IE8 we'll lighten the color */
background: ligthen($brand-gray-medium, 50%);
/* Otherwise we'll rely on stacked opacities */
background: rgba($brand-gray-medium, 0.75);
}
}
}
.vjs-fullscreen {
max-height: none;
}
}
.content-details {
margin-top: 40px;
margin-bottom: 40px;
.content-title {
@extend .h2 !optional;
font-family: $primary-font;
}
.content-author {
font-family: $secondary-font;
margin-bottom: 0;
a {
color: $black;
text-transform: uppercase;
&:hover {
color: $brand-red-hover;
}
}
}
.content-views {
margin-bottom: 0;
margin-top: 10px;
}
.contest-sponsors {
img {
margin-bottom: 5px;
max-height: 100px;
&:not(:last-child) {
margin-right: 5px;
}
}
}
.content-tags, .content-contests {
@extend .title-call;
font-family: $primary-font;
line-height: 1.5;
margin-bottom: 0;
margin-top: 8px;
a {
color: black;
font-weight: normal;
&:after {
content: ', ';
}
&:last-child:after {
content: '';
}
}
}
.left-col, .right-col {
@include grid-col(12);
@include breakpoint(large){
@include grid-col(6);
}
h2, h3, p {
margin-bottom: 0;
}
}
.right-col {
@include breakpoint(large){
text-align: right;
}
}
}
.content-icons-group {
margin-top: 10px;
.has-tip {
background-position: center;
background-repeat: no-repeat;
background-size: contain;
border-bottom: none;
cursor: initial;
height: 40px;
vertical-align: middle;
width: 40px;
&:not(:last-child) {
margin-right: 10px;
}
}
.ic-premio {
background-image: url('ic-premio-preto.svg');
}
.ic-destaque {
background-image: url('ic-destaque-preto.svg');
}
.ic-mapa {
background-image: url('ic-mapa-preto.svg');
&:hover {
background-image: url('ic-mapa-preto-hover.svg');
}
}
}
.video-license {
margin-left: 10px;
&:before {
background: url('ic-cc.svg') no-repeat left center;
background-size: contain;
content: '';
width: 20px;
height: 20px;
padding-left: 25px;
}
}
.content-rating {
@extend .content-views;
.has-tip {
border-bottom: none;
cursor: pointer;
}
> .has-tip {
cursor: initial;
}
}
/******relacionados*******/
.tabs-content {
@include grid-row;
border: none;
padding: 0;
&> .tabs-panel {
padding: 0;
}
}
.tabs-panel {
@include grid-col(12);
// margin-bottom: 40px;
}
.related-content {
@include is-container();
.content-sub-container {
@include grid-col-row;
margin-bottom: 40px;
}
}
.content-button-group {
span {
@extend .h3;
font-size: 24px;
margin-right: 20px;
}
a {
@extend .h3;
color: $black;
&:hover,
&:focus {
color: $brand-red;
}
&:not(:last-child) {
margin-right: 20px;
}
&.is-active {
color: $brand-red;
border-bottom: 3px solid $brand-red;
}
}
}
.inline-grid {
.tabs-title {
&:not(:last-child) {
margin-right: 20px;
}
a {
@extend h3;
color: #000;
padding: 0;
&:hover {
color: $brand-red;
}
}
> a:focus, > a[aria-selected='true'] {
background-color: #fff;
}
&:hover {
color: $brand-red;
}
&.is-active a {
border-bottom: 3px solid $brand-red;
color: $brand-red;
}
}
}
.tabs {
border: none;
}
.comments-list {
@include grid-col(12);
@include breakpoint(large) {
@include grid-col(10);
}
}
.comment-box {
@include media-object-container;
border-top: 1px solid $brand-gray-medium;
margin: 0;
padding-top: 25px;
.comments-list > &:last-of-type {
border-bottom: 1px solid $brand-gray-medium;
margin-bottom: 20px;
}
.comment-box-section {
@include media-object-section(20px);
.thumbnail {
border: none;
box-shadow: none;
width: 75px;
&:hover,
&:focus {
box-shadow: none;
}
img {
border-radius: 50%;
}
}
.comment-author {
color: $brand-red;
}
p {
font-size: 14px;
}
.comment-likes {
cursor: pointer;
margin-left: 20px;
&:before {
background: url('ic-like.svg') no-repeat left center;
content: '';
width: 18px;
height: 20px;
padding-left: 23px;
}
&:hover:before {
background-image: url('ic-like-hover.svg');
}
}
}
}
.comment-compose-box {
@extend .comment-box;
border-top: none;
padding-bottom: 25px;
width: 100%;
.input-section {
text-align: right;
width: 100%;
textarea {
font-size: 14px;
}
}
}
......@@ -13,5 +13,6 @@
*= require_self
*= require foundation_and_overrides
*= require colorbox-rails
*= require video-js
*/
......@@ -56,4 +56,5 @@
@import 'main';
@import 'header';
@import 'form-section';
@import 'content-detailed';
@import 'footer';
class ContentsController < ApplicationController
before_action :set_content, only: [:show]
before_action :find_last_encoded_video, only: [:show]
protect_from_forgery with: :null_session, only: :zencoder_callback
# GET /contents/1
# GET /contents/1.json
def show
@video = @encoded_video.video
end
# GET /contents/new
......@@ -20,7 +22,7 @@ class ContentsController < ApplicationController
respond_to do |format|
if @content.save
format.html { redirect_to @content, notice: I18n.t('successfully_created_video') }
format.html { redirect_to root_path, notice: I18n.t('successfully_created_video') }
else
format.html { render :new }
end
......@@ -54,4 +56,9 @@ class ContentsController < ApplicationController
def content_params
params.require(:content).permit(:title, :user_id, :adult, :rating, :soundtrack, :view_count, :deleted, :zip_code, :director, :co_director, :team, :allow_comments, :video)
end
def find_last_encoded_video
@encoded_video = @content.encoded_contents.last
redirect_to root_path, notice: I18n.t('video_has_not_finished_encoding') unless @encoded_video.state == 'finished'
end
end
......@@ -10,6 +10,6 @@ class RequestZencoderJob < ApplicationJob
private
def notification_url
Rails.env.test? ? [url: 'http://zencoderfetcher/'] : [url: ZencoderSettings.notifications.url]
(Rails.env.test? || Rails.env.development?) ? [url: 'http://zencoderfetcher/'] : [url: ZencoderSettings.notifications.url]
end
end
......@@ -14,6 +14,8 @@ class Content < ApplicationRecord
has_many :encoded_contents
belongs_to :user
private
def send_to_zencoder
......
......@@ -8,4 +8,5 @@ class User < ApplicationRecord
validates :email, confirmation: true
has_one :profile
has_many :contents
end
<div class="content-details">
<div class="left-col">
<h2 class="content-title"><%= content.title %></h2>
<div class="inline-grid">
<h3 class="content-author"><%= t('.by') %> <%= content.user.profile.full_name %></h3>
<!-- TODO: Uncomment after the follow routes are defined
<a href=<#= follow_path(video.user) %> class="follow-button small has-tip top" data-tooltip aria-haspopup="true" class="has-tip top ic-premio" data-disable-hover='false' tabindex=1 title="Seguir usuário">
<i class="fa fa-long-arrow-left"></i>
<i class="fa fa-long-arrow-left"></i>
<i class="fa fa-long-arrow-left"></i>
<i class="fa fa-long-arrow-left"></i>
</a>
-->
</div>
<p><%= content.user.profile.city %> - <%= content.user.profile.state %> <%= content.user.profile.country %></p>
<p><%= t('.added_on', date: content.created_at.to_date) %><span class="video-license">BY-NC-SA</span></p>
</div>
<div class="right-col">
<!-- TODO: Uncomment after video awards and features are implemented
<div class="content-icons-group">
<# if video.awarded? %>
<span data-tooltip aria-haspopup="true" class="has-tip top ic-premio" data-disable-hover='false' tabindex=1 title="<#= t('.awarded')%>"></span>
<# end %>
<# if featured? video %>
<span data-tooltip aria-haspopup="true" class="has-tip top ic-destaque" data-disable-hover='false' tabindex=1 title="<#= t('.featured')%>"></span>
<# end %>
</div>
-->
<h3 class="content-views"><%= content.view_count %> <%= t('.views') %></h3>
<!-- TODO: Uncomment after content rating backed is complete
<div class="content-rating">
<# if user_signed_in? %>
<#= form_tag '/votes', method: :post, remote: true do %>
<#= hidden_field_tag 'vote[content_id]', video.id %>
<%# TODO: Votes will be public only on public contests %>
<#= hidden_field_tag 'public_vote', false %>
<input type="range" min="0" max="5" value="<#= video.average_of_users_grade_rounded %>" step="0.5" id="content-rating-val" name="vote[grade]">
<div class="rateit" data-rateit-backingfld="#content-rating-val" data-rateit-ispreset="true" data-rateit-starwidth="20" data-rateit-starheight="20"></div>
<div>
<button type="submit" class="evaluate-button"><#= t('.evaluate') %></button>
</div>
<# end %>
<# else %>
<#= t('.needs_to_login_to_evaluate') %>
<# end %>
</div>
-->
</div>
<div class="columns small-12">
<!-- Uncomment after the tags backend is complete
<h3 class="content-tags"><#= t('.contents.show.details.tags') %>
<# if video.show_tags.empty? %>
<#= t('.none') %>
<# else %>
<#= video.show_tags %>
<# end %>
</h3>
-->
<!-- Uncomment after the contests backend is complete
<h3 class="content-contests"> <#= t('.contents.show.details.contests') %>
<# if video.contests.empty? %>
<#= t('.none') %>
<# else %>
<# video.contests.each do |contest| %>
<#= link_to(contest.name, contest_path(id: contest)) %>
<# end %>
<# end %>
</h3>
-->
</div>
</div>
<div class="player-box">
<%# FIXME: Poltergeist server won't recognize the video source if put on a source tag %>
<video id="video-<%= content.id %>" class="video-js" controls preload="none" data-setup="{}" src="<%= video.url %>" type="video/mp4">
<p class="vjs-no-js">
<%= t('.video_js_support_message_html') %>
</p>
</video>
</div>
<p id="notice"><%= notice %></p>
<p>
<strong>Title:</strong>
<%= @content.title %>
</p>
<p>
<strong>User:</strong>
<%= @content.user_id %>
</p>
<p>
<strong>Adult:</strong>
<%= @content.adult %>
</p>
<p>
<strong>Rating:</strong>
<%= @content.rating %>
</p>
<p>
<strong>Soundtrack:</strong>
<%= @content.soundtrack %>
</p>
<p>
<strong>View count:</strong>
<%= @content.view_count %>
</p>
<p>
<strong>Deleted:</strong>
<%= @content.deleted %>
</p>
<p>
<strong>Zip code:</strong>
<%= @content.zip_code %>
</p>
<p>
<strong>Director:</strong>
<%= @content.director %>
</p>
<p>
<strong>Co director:</strong>
<%= @content.co_director %>
</p>
<p>
<strong>Team:</strong>
<%= @content.team %>
</p>
<p>
<strong>Allow comments:</strong>
<%= @content.allow_comments %>
</p>
<%= link_to 'Back', contents_path %>
<main>
<div class="content-detailed-section">
<div class="autoplay-section">
<div class="autoplay-label"><%= t('.autoplay') %></div>
<div class="switch tiny">
<input class=