First version

This commit is contained in:
邱博亞 2024-08-14 00:06:11 +08:00
commit cc69740245
41 changed files with 2179 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
.bundle/
log/*.log
pkg/
test/dummy/db/*.sqlite3
test/dummy/db/*.sqlite3-journal
test/dummy/log/*.log
test/dummy/tmp/
test/dummy/.sass-cache

14
Gemfile Normal file
View File

@ -0,0 +1,14 @@
source "https://rubygems.org"
# Declare your gem's dependencies in bulletin.gemspec.
# Bundler will treat runtime dependencies like base dependencies, and
# development dependencies will be added by default to the :development group.
gemspec
# Declare any dependencies that are still in development here instead of in
# your gemspec. These might include edge Rails or gems from your path or
# Git. Remember to move these dependencies to your gemspec before releasing
# your gem to rubygems.org.
# To use debugger
# gem 'debugger'

20
MIT-LICENSE Normal file
View File

@ -0,0 +1,20 @@
Copyright 2014 YOURNAME
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

3
README.rdoc Normal file
View File

@ -0,0 +1,3 @@
= Video Programs
This project rocks and uses MIT-LICENSE.

32
Rakefile Normal file
View File

@ -0,0 +1,32 @@
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end
require 'rdoc/task'
RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'Video Programs'
rdoc.options << '--line-numbers'
rdoc.rdoc_files.include('README.rdoc')
rdoc.rdoc_files.include('lib/**/*.rb')
end
Bundler::GemHelper.install_tasks
require 'rake/testtask'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = false
end
task default: :test

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,111 @@
.video-program .category-title {
width: 100%;
}
.video-program.card-group .card-body img {
object-fit: cover;
}
.video-program.card-group .row {
position: relative;
display: flex;
flex-wrap: wrap;
width: 100%;
}
.video-program.card-group .card-back {
transform: rotateY(180deg) translateX(-100%);
position: absolute;
backface-visibility: hidden;
transition: transform 300ms;
transition-timing-function: linear;
display: block;
width: 100%;
height: 100%;
top: 0;
background: white;
color: black;
}
.video-program.card-group .card.card-flip.h-100:nth-child(4n) {
margin-right: 0em;
}
.video-program.card-group .card.card-flip.h-100 {
position: relative;
width: 25%;
width: calc( 25% - 0.75em);
background: white;
margin-right: 1em;
margin-bottom: 1em;
}
@media (max-width: 768px){
.video-program.card-group .card.card-flip.h-100 {
width: 50%;
width: calc( 50% - 0.5em);
}
.video-program.card-group .card.card-flip.h-100:nth-child(2n) {
margin-right: 0em;
}
}
@media (max-width: 575px){
.video-program.card-group .card.card-flip.h-100 {
width: 100%;
margin-right: 0em;
}
}
.video-program.card-group h3.card-title {
padding: 0.5em;
margin: 0;
font-size: 1.2em;
}
.video-program.card-group .card-front{
backface-visibility: hidden;
width: 100%;
height: 100%;
}
.video-program.card-group .card-front .card-footer {
position: absolute;
color: #fff;
left: 0;
bottom: 0;
overflow: hidden;
text-overflow: ellipsis;
max-height: 60%;
background: linear-gradient(transparent, rgba(0, 0, 0, .2) 20%, rgba(0, 0, 0, .8) 90%);
}
.video-program.card-group .card.card-flip.h-100:hover .card-back {
transform: rotateY(0deg);
}
.video-program.card-group .card-button-group{
bottom: 0;
right: 0;
position: absolute;
display: flex;
vertical-align: middle;
}
.video-program.card-group .card-body{
width: 100%;
position: inherit;
display: flex;
flex-direction: column;
height: 100%;
}
.video-program.card-group .card-button-group a {
color: #fff;
display: block;
background: #6c757d;
padding: 0.5em;
width: 2.3em;
height: 2.3em;
margin-right: 0.1em;
border-radius: 0;
}
.video-program.card-group .card-button-group a:hover {
color: #fff;
background-color: #5a6268;
border-color: #545b62;
}
.video-program.card-group .card-button-group a:focus {
color: #fff;
outline: 0.1em dotted !important;
}
.video-program.card-group .card-button-group span {
line-height: 2;
}

View File

@ -0,0 +1,106 @@
# encoding: utf-8
require 'rubyXL'
class Admin::VideoProgramsController < OrbitAdminController
before_action ->(module_app = @app_title) { set_variables module_app }
before_action :set_video_program, only: [:edit, :destroy]
def initialize
super
@app_title = "video_program"
end
def index
VideoProgram.remove_expired_status
@tags = @module_app.tags
@table_fields = [:status, :category, :title, "video_program.start_date", "video_program.end_date", :last_modified]
@current_user = current_user
if params[:sort].blank?
params[:sort] = 'post_date'
params[:order] = 'desc'
end
@categories = @module_app.categories.enabled.authorized(current_user)
@filter_fields = filter_fields(@categories, @tags)
@video_programs = VideoProgram.where(:category_id.ne=>nil)
.order_by(sort)
.with_categories(filters("category"))
.with_tags(filters("tag"))
.with_status(filters("status"))
@video_programs = search_data(@video_programs,[:title]).page(params[:page]).per(10)
if request.xhr?
render :partial => "index"
end
end
def new
@tags = @module_app.tags
@statuses = []
@video_program = VideoProgram.new
end
def create
bps = video_program_params
video_program = VideoProgram.new(bps)
if !bps['video_program_links_attributes'].nil?
bps['video_program_links_attributes'].each do |idx,link|
bps['video_program_links_attributes'].delete(idx.to_s) if link['url'].blank?
end
end
video_program.create_user_id = current_user.id
video_program.update_user_id = current_user.id
video_program.save
redirect_to params['referer_url']
end
def edit
if can_edit_or_delete?(@video_program)
@tags = @module_app.tags
@categories = @module_app.categories.enabled.authorized(current_user)
@statuses = []
else
render_401
end
end
def update
uid = params[:id].split('-').last
video_program = VideoProgram.find_by(:uid=>uid)
bps = video_program_params
bps[:tags] = bps[:tags].blank? ? [] : bps[:tags]
if !bps['video_program_links_attributes'].nil?
bps['video_program_links_attributes'].each do |idx,link|
bps['video_program_links_attributes'].delete(idx.to_s) if link['url'].blank?
end
end
bps[:update_user_id] = current_user.id
video_program.update_attributes!(bps)
now_video_program_page = VideoProgram.where(:title.ne => "")
.order_by(sort).map(&:id).map.with_index.select{|v,i| v==video_program.id}[0][1] rescue nil
now_video_program_page = now_video_program_page.nil? ? 0 : ((now_video_program_page+1).to_f/10).ceil
redirect_to admin_video_programs_path(:page=>now_video_program_page)
end
def destroy
@video_program.destroy
redirect_to "/admin/video_programs"
end
# def delete
# if params[:ids]
# VideoProgram.any_in(:uid => params[:ids]).destroy_all
# end
# redirect_to "/admin/video_programs"
# end
private
def set_video_program
@video_program = VideoProgram.find(params[:id])
end
def video_program_params
params.require(:video_program).permit!
end
end

View File

@ -0,0 +1,228 @@
class VideoProgramsController < ApplicationController
include VideoProgramsHelper
def initialize
super
@app_title = 'video_program'
end
def short_desc(str, len)
if str && str.length > len
str[0...len] + '...'
else
str
end
end
def index
VideoProgram.remove_expired_status
sorted,total_pages = get_sorted_video_programs
#If no data , hide title&table
if sorted.count == 0
display_class = "hide"
categories = []
else
grouped_data = sorted.group_by(&:category_id)
category_title_map = Category.where(:id.in=>grouped_data.keys).pluck(:id, "title.#{I18n.locale}").map{|k,v| [k, v.values[0]]}.to_h
categories = grouped_data.map do |category_id, video_programs|
{
"category-title" => category_title_map[category_id],
"video-programs" => video_programs.map do |vp|
statuses = vp.statuses_with_classname.collect do |status|
{
"status" => status["name"],
"status-class" => "status-#{status['classname']}"
}
end
episodes = vp.episodes || 0
{
"title" => vp.title,
"subtitle" => short_desc(vp.subtitle, 100),
"episodes" => episodes,
"episodes_text" => t("video_program.episodes_text",{:num=> episodes}),
"thumb-src" => (vp.image.thumb.url || "/assets/video_program/default.jpg"),
"link_to_show" => OrbitHelper.url_to_show(vp.to_param),
"statuses" => statuses
}
end
}
end
end
{
"categories" => categories,
"extras" => {
"program_notes-head" => t('video_program.program_notes'),
"video_notes-head" => t('video_program.video_notes'),
"play-head" => t('video_program.play'),
"view-count-head" => t('video_program.table.view_count'),
"display_class" => display_class
},
"total_pages" => total_pages
}
end
def get_file
@url = request.path
begin
if @url.match(/\/\.\./)
render :file => "#{Rails.root}/app/views/errors/404.html", :layout => false, :status => :not_found, :content_type => 'text/html'
return
end
file = VideoProgramFile.find(params[:id])
if File.basename(file.file.path) != URI.decode(params[:f_name])
render :file => "#{Rails.root}/app/views/errors/403.html", :layout => false, :status => :not_found, :content_type => 'text/html'
return
end
@url = file.file.url
if file.can_access?(OrbitHelper.current_user)
@path = file.file.path rescue ""
@filename = @path.split("/").last
@ext = @path.split("/").last.to_s.split(".").last
if @ext == "png" || @ext == "jpg" || @ext == "bmp" || @ext == "pdf"
render "archives/download_file.html",:layout=>false
else
if (current_site.accessibility_mode rescue false)
render "archives/redirect_to_file.html",:layout=>false
return
else
send_file(@path)
return
end
end
else
render :file => "#{Rails.root}/app/views/errors/403.html", :layout => false, :status => :not_found, :content_type => 'text/html'
return
end
rescue
render :file => "#{Rails.root}/app/views/errors/404.html", :layout => false, :status => :not_found, :content_type => 'text/html'
return
end
end
def show_local_video_program(uid)
locale = OrbitHelper.get_site_locale.to_s
video_program = VideoProgram.where(:uid => uid).first
return nil if video_program.nil?
url_to_edit = OrbitHelper.user_can_edit?(video_program) ? "/admin/video_program/#{video_program.id.to_s}/edit" : ""
return {} if (video_program.category.disable rescue false)
tags = video_program.tags.map{|tag| {
"tag" => tag.name ,
"url" => OrbitHelper.page_for_tag(tag)
} }
files = video_program.video_program_files.to_fronted(locale)
links = video_program.video_program_links.map{|link| { "link_url" => link.url, "link_title" => (link.title.blank? ? link.url : link.title) } } rescue []
update_user = video_program.update_user.member_profile.name rescue ""
desc = OrbitHelper.get_default_value(video_program.image_description, "VideoProgram image")
request = OrbitHelper.request
meta_desc = video_program.subtitle.nil? || video_program.subtitle == "" ? short_desc(video_program.video_notes, 200) : video_program.subtitle
OrbitHelper.render_meta_tags([{"property" => "og:title", "content" => video_program.title},{"property" => "og:site_name", "content" => Site.first.title},{"property" => "og:url", "content" => request.original_url.split("?").first},{"property" => "og:description", "content" => meta_desc},{"property" => "og:image", "content" => "#{request.base_url}#{video_program.image.url}"},{"property" => "og:type", "content" => "Article"}])
subtitle = nil
image_html = nil
video_image_html = nil
img_description = nil
video_img_description = nil
subtitle = video_program.subtitle
if video_program.display_image && video_program.image.present?
img_description = OrbitHelper.get_default_value(video_program.image_description, video_program.title)
image_html = "<img src=\"#{video_program.image.url}\" alt=\"#{img_description}\" />"
end
if video_program.display_video_image && video_program.video_image.present?
video_img_description = OrbitHelper.get_default_value(video_program.video_image_description, video_program.title)
video_image_html = "<img src=\"#{video_program.video_image.url}\" alt=\"#{video_img_description}\" />"
end
if video_program.video_external_link.present?
video_external_link = video_program.video_external_link
video_external_link_class = ""
else
video_external_link = "javascript:;"
video_external_link_class = "disabled"
end
video_program_carousel_images = video_program.video_program_carousel_images.map{|image| {"src"=>image.file.url,"description"=>image.description.to_s,"description_text"=>image.description_text }}
resume_btn_title = t("plugin_control.resume")
pause_btn_title = t("plugin_control.pause")
prev_btn_title = t("plugin_control.prev")
next_btn_title = t("plugin_control.next")
episodes_text = t("video_program.episodes_text",{:num=> video_program.episodes})
grouped_data = video_program.albums.asc(:order).group_by{|a| a.tag_ids.first}
tag_sort_number_map = {}
tag_title_map = Tag.where(:id.in=>grouped_data.keys).pluck(:id, "name.#{I18n.locale}", :tmp_sort_number).map do |k,v, sort_number|
tag_sort_number_map[k] = sort_number
[k, v.values[0]]
end.to_h
episodes_albums = grouped_data.sort_by{|k, v| tag_sort_number_map[k].to_i}.map.with_index do |(tag_id, albums), i|
tag_name = tag_id ? tag_title_map[tag_id] : nil
images = albums.map do |album|
skip_tag_ids = album.tag_ids
album.album_images.asc(:order).map do |album_image|
{
"img-src" => album_image.file.url,
"img-tags" => album_image.tags.map{|tag|
next if skip_tag_ids.include?(tag.id)
{
"tag" => tag.name,
}
}.compact,
"ep_title" => album_image.title,
"ep_desc" => album_image.description
}
end
end.flatten
{
"images_tag" => tag_name,
"images" => images,
"tab-class" => (i == 0 ? 'active in' : ''),
"tab-index" => i
}
end
data = {
"tags" => tags,
"video_program_files" => files,
"video_program_links" => links,
"episodes_albums" => episodes_albums,
"data" => {
"title-head" => t('video_program.title'),
"program_notes-head" => t('video_program.program_notes'),
"actor_notes-head" => t('video_program.actor_notes'),
"video_notes-head" => t('video_program.video_notes'),
"carousel_image-head" => t('video_program.carousel_image'),
"episodes_albums-head" => t('video_program.episodes_albums'),
"play-head" => t('video_program.play'),
"program_notes" => video_program.program_notes,
"program_notes_class" => (video_program.program_notes.present? ? "" : "hide"),
"actor_notes" => video_program.actor_notes,
"actor_notes_class" => (video_program.actor_notes.present? ? "" : "hide"),
"video_notes" => video_program.video_notes,
"episodes_albums_class" => (episodes_albums.present? ? "" : "hide"),
"title" => video_program.title,
"subtitle" => subtitle,
"image_html" => image_html,
"video_image_html" => video_image_html,
"img_description" => img_description,
"video_img_description" => video_img_description,
"alt_title" => desc,
"resume_btn_title" => resume_btn_title,
"pause_btn_title" => pause_btn_title,
"prev_btn_title" => prev_btn_title,
"next_btn_title" => next_btn_title,
"carousel_display_style" => (video_program_carousel_images.count == 0 ? 'display: none;' : video_program.carousel_image_width ? "width: #{video_program.carousel_image_width};margin: auto;" : nil),
"carousel_count" => video_program_carousel_images.count,
"video_external_link" => video_external_link,
"video_external_link_class" => video_external_link_class,
"episodes_text" => episodes_text,
"carousel_image_class" => (video_program_carousel_images.present? ? "" : "hide")
},
"impressionist" => video_program,
"url_to_edit"=>url_to_edit
}
data['data']['video_program_carousel_images'] = (video_program_carousel_images.present? ? render_ad_banner(video_program_carousel_images,data['data']) : nil)
data
end
def show
params = OrbitHelper.params
uid = params[:uid].to_s
show_local_video_program(uid)
end
end

View File

@ -0,0 +1,19 @@
module Admin::VideoProgramsHelper
def cal_url_to_show(module_app, model)
pages = Page.where(:module=>module_app.key).order_by(id: :asc)
if model.respond_to?(:category_id) && model.category_id
pages = pages.any_of({:categories.in => ['all', model.category_id.to_s]}, {:categories=> {'$size'=> 0}})
end
puts "pages = #{pages}"
page_data_list = pages.pluck(:url, :categories).sort_by{|page_data|
page_data[1].length == 1 && page_data[1] != 'all' ? 0 : 1
}
if page_data_list
show_page_url = page_data_list[0][0]
return "/#{I18n.locale}#{show_page_url}/#{model.to_param}"
end
return '#'
end
end

View File

@ -0,0 +1,256 @@
module VideoProgramsHelper
def render_ad_banner(event_carousel_images,data)
("<div class=\"carousel_images\">
<div class=\"w-ba-banner ba-banner-widget-1\">
<div class=\"w-ba-banner__wrap cycle-slideshow\"
data-list=\"event_carousel_images\"
data-level=\"0\"
data-cycle-slides=\".video_program_carousel_slide\"
data-cycle-log=\"false\"
data-cycle-auto-height=\"0\"
data-cycle-speed=\"300\"
data-cycle-timeout=\"5000\"
data-cycle-fx=\"fade\"
data-pager-active-class=\"active-slide\"
data-cycle-swipe=true
data-cycle-swipe-fx=\"scrollHorz\"
>" +
event_carousel_images.collect do |e|
"<div class=\"w-ba-banner__slide video_program_carousel_slide\"
data-cycle-title=\"#{e['description_text']}\"
>
<img class=\"w-ba-banner__image banner-responsive\" src=\"#{e['src']}\" alt=\"#{e['description_text']}\" title=\"#{e['description_text']}\">
<div class=\"ad-overlay w-ad-banner__overlay event_carousel__overlay\">
<p><strong class=\"carousel__description\">#{e['description']}</strong></p>
</div>
<div class=\"transitionfade\"></div>
</div>"
end.join+
"</div>
<ul class=\"controlplay\"><a class=\"resume-slide\" title = \"#{data['resume_btn_title']}\"><i></i></a><a class=\"pause-slide\" title = \"#{data['pause_btn_title']}\"><i></i></a></ul>
<ul class=\"button-mid\">
<i class=\"fa fa-angle-left prev-button\" aria-hidden=\"true\" title = \"#{data['prev_btn_title']}\"></i>
<i class=\"fa fa-angle-right next-button\" aria-hidden=\"true\" title = \"#{data['next_btn_title']}\"></i>
</ul>
</div>
<div style=\"position: relative;\">
<h4><span class=\"active_slide\">1</span>/#{data['carousel_count']}</h4>
<ul class=\"carousel_images_slide w-video_program__list row list-unstyled\" data-level=\"0\" data-list=\"event_carousel_images\">" +
event_carousel_images.collect do |e|
"<li class=\"carousel_img_item col-md-3 col-sm-6\">
<div class=\"carousel_img-wrap\">
<img class=\"carousel_img\" src=\"#{e['src']}\" alt=\"#{e['description_text']}\" title=\"#{e['description_text']}\">
</div>
</li>"
end.join +
"</ul>
<ul class=\"button-mid\">
<i class=\"fa fa-angle-left prev-button prev_img\" aria-hidden=\"true\" title = \"#{data['prev_btn_title']}\"></i>
<i class=\"fa fa-angle-right next-button next_img\" aria-hidden=\"true\" title = \"#{data['next_btn_title']}\"></i>
</ul>
</div>
</div>").html_safe
end
def get_feed_annc(type,site_source,locale,categories=nil)
ma_key = 'video_programs'
if categories.nil?
if type == "index"
categories = Array(OrbitHelper.page_categories)
elsif type == "widget"
categories = Array(OrbitHelper.widget_categories)
else
categories = []
end
end
categories = ["all"] if categories.length==0
if categories.include?("all")
feeds = SiteFeedAnnc.where(:channel_key => ma_key)
else
feeds = SiteFeedAnnc.where(:channel_key => ma_key, :merge_with_category.in => categories)
end
if feeds.count > 0
temp_ids = []
data = feeds.collect do |feed|
feed.all_contents_for_feed(site_source,locale,type=='widget')
end.flatten.compact
else
data = []
end
data
end
def get_feed_video_programs(type,site_source=nil,categories=nil,max_len=nil)
locale = OrbitHelper.get_site_locale.to_s
if !(defined? SiteFeedAnnc).nil?
fans = get_feed_annc(type,site_source,locale,categories)
else
feed_anns = OrbitHelper.get_feed_for_module(type)
fans = []
feed_anns.each do |fa|
next if !site_source.nil? && site_source != fa["source-site-title"]
status = {
"status" => "<a href='#{fa["source-site"]}' target='_blank' class='feed-source'>#{fa["source-site-title"]}</a>",
"status-class" => "status-source"
}
files = fa["event_news_files"].collect{|bf| { "file_url" => bf["url"], "file_title" => (fa["title_translations"][locale].blank? ? File.basename(fa["url"]) : fa["title_translations"][locale] rescue '') }} rescue []
links = fa["event_news_links"].map{|link| { "link_url" => link["url"], "link_title" => (link["title_translations"][locale].blank? ? link["url"] : link["title_translations"][locale]) } } rescue []
event_time_formated = a.event_time_formated
s = DateTime.parse(fa["event_date"]) rescue nil
e = DateTime.parse(fa["event_end_date"]) rescue nil
date_parse_format = fa["all_day"] ? '%Y-%m-%d' : '%Y-%m-%d %H:%M'
if s.blank? && e.blank?
event_time_formated = ""
elsif s.blank?
event_time_formated = s.strftime(date_parse_format)
elsif e.blank?
event_time_formated = "~ " + e.strftime(date_parse_format)
else
if s.to_date == e.to_date
date_str = s.strftime('%Y-%m-%d')
s_time = s.strftime('%H:%M')
e_time = e.strftime('%H:%M')
event_time_formated = "#{date_str} #{s_time} ~ #{e_time}"
else
event_time_formated = s.strftime(date_parse_format) + " ~ " + e.strftime(date_parse_format)
end
end
x = {
"event_news_links" => links,
"event_news_files" => files,
"event_carousel_images" => fa["event_carousel_images"].to_a,
"title" => fa["title_translations"][locale],
"speaker-css" => (fa["speaker_translations"][locale].blank? ? "display: none;" : ""),
"host-css" => (fa["host_translations"][locale].blank? ? "display: none;" : ""),
"place-css" => (fa["place_translations"][locale].blank? ? "display: none;" : ""),
"event-time-css" => (event_time_formated.blank? ? "display: none;" : ""),
"notes-css" => (fa["notes_translations"][locale].blank? ? "display: none;" : ""),
"event-time-formated" => event_time_formated,
"speaker" => (fa["speaker_translations"][locale].to_s rescue ""),
"place" => (fa["place_translations"][locale].to_s rescue ""),
"host" => (fa["host_translations"][locale].to_s rescue ""),
"notes" => (fa["notes_translations"][locale].to_s rescue ""),
"subtitle" => fa["subtitle_translations"][locale],
"statuses" => [status],
"category" => fa["category"],
"postdate" => (DateTime.parse(fa["event_date"]) rescue DateTime.now),
"event_date" => (DateTime.parse(fa["event_date"]) rescue DateTime.now),
"author" => fa["author"],
"source-site" => "<a href='#{fa["source-site"]}' target='_blank' class='feed-source'>#{fa["source-site-title"]}</a>",
"source-site-title" => fa["source-site-title"],
"source-site-link" => fa["source-site"],
"link_to_show" => OrbitHelper.url_to_show(fa["params"]),
"target" => "_self",
"img_src" => fa["image"]["thumb"] || "/assets/video_programs-default.jpg",
"img_description" => fa["image_description_translations"][locale],
"more" => t("video_programs.more"),
"view_count" => ""
}
if (!x["title"].empty? rescue false)
fans << x
end
end
end
fans
end
def filter_by_keywords(sorted,keywords,stime,etime)
kflag = keywords.blank?
sflag = stime.blank?
eflag = etime.blank?
stime = stime.to_s.split('/')
stime = Time.zone.local(*stime) rescue nil
etime = etime.to_s.split('/')
etime = Time.zone.local(*etime) rescue nil
if !kflag || !sflag || !eflag
sorted.select{|anns|
if kflag
flag = true
else
if anns["source-site"].present?
title = Nokogiri::HTML(anns["title"].to_s).text
else
title = Nokogiri::HTML(anns.title.to_s).text
end
flag = title.include?(keywords.to_s)
end
flag
}
else
sorted
end
end
def get_sorted_video_programs(data_count=nil)
params = OrbitHelper.params
locale = OrbitHelper.get_site_locale.to_s
page_number = OrbitHelper.page_number.to_i
page_number = 1 if page_number == 0
page_data_count = data_count || OrbitHelper.page_data_count.to_i
feeds_anns = []
page = OrbitHelper.page rescue nil
page = Page.where(url: params['url']).first if page.nil?
if @type == "show_widget"
tags = @tags
categories = @categories
else
tags = page.tags
tags = params[:tags] if params[:tags].present?
categories = params['category']=='all' ? (page.categories || []) : (Array(params['category']) rescue (page.categories || []))
if params['category'].present? && tags.blank?
tags = ["all"]
end
end
if params["source"].blank?
if @type == "show_widget"
if params[:uids].blank?
video_programs = VideoProgram.where(:title.nin => ["",nil],:is_preview.in=>[false,nil])
.can_display_and_sorted
.filter_by_categories(categories,false).filter_by_tags(tags).to_a
else
member_prfile = MemberProfile.any_in(:uid=>params[:uids])
user_ids = member_prfile.map{|m| m.user.id rescue nil}.select{|id| !id.nil?}
video_programs = VideoProgram.where(:title.nin => ["",nil],:is_preview.in=>[false,nil],:create_user_id.in=>user_ids)
.can_display_and_sorted
.filter_by_categories(categories,false).filter_by_tags(tags).to_a
end
else
video_programs = VideoProgram.where(:title.nin => ["",nil],:is_preview.in=>[false,nil])
.can_display_and_sorted
.filter_by_categories(categories,false).filter_by_tags(tags).to_a
end
if false #!(defined? SiteFeed).nil?
if @type != "show_widget"
feeds_anns = get_feed_video_programs("index",nil,nil,page_number*page_data_count)
else
feeds_anns = []
end
end
else
video_programs = []
if false # @type != "show_widget"
feeds_anns = get_feed_video_programs("index",params["source"],nil,page_number*page_data_count)
else
feeds_anns = []
end
end
if feeds_anns.present?
if video_programs.count != 0
top_anns = video_programs.select{|v| v.is_top} + feeds_anns.select{|v| v['is_top']}
rest_all_anns = feeds_anns.select{|v| v['is_top'] != true} + video_programs.select{|v| !v.is_top}
rest_anns = rest_all_anns.sort_by { |a| tmp=a["postdate"].blank?;[tmp ? 0 : 1, tmp ? nil : a["postdate"].to_time] }.reverse
all_sorted = top_anns.sort_by { |a| tmp=a["postdate"].blank?;[tmp ? 0 : 1, tmp ? nil : a["postdate"].to_time] }.reverse + rest_anns
else
all_sorted = feeds_anns.select{|v| v['is_top']}.sort_by { |a| tmp=a["postdate"].blank?;[tmp ? 0 : 1, tmp ? nil : a["postdate"].to_time] }.reverse + feeds_anns.select{|v| v['is_top'] != true}.sort_by { |a| tmp=a["postdate"].blank?;[tmp ? 0 : 1, tmp ? nil : a["postdate"].to_time] }.reverse
end
all_filter = filter_by_keywords(all_sorted,params[:keywords],params[:stime],params[:etime])
else
all_filter = filter_by_keywords(video_programs,params[:keywords],params[:stime],params[:etime])
end
if page_data_count != 0
sorted = all_filter[(page_number-1)*page_data_count...page_number*page_data_count]
else
sorted = all_filter
end
annc_count = all_filter.count
total_pages = page_data_count == 0 ? 1 : (annc_count.to_f / page_data_count).ceil
[sorted,total_pages]
end
end

0
app/models/.keep Normal file
View File

View File

@ -0,0 +1,80 @@
class VideoProgram
include Mongoid::Document
include Mongoid::Timestamps
include OrbitModel::Status
include OrbitModel::Impression
# encoding: utf-8
include OrbitTag::Taggable
include OrbitCategory::Categorizable
include Slug
field :custom_carousel_image_width, type: String, default: ""
field :display_video_image, :type => Boolean, :default => false
mount_uploader :video_image, ImageUploader
field :video_image_description, localize: true
field :display_image, :type => Boolean, :default => false
mount_uploader :image, ImageUploader
field :image_description, localize: true
field :title, as: :slug_title, type: String, localize: true
field :subtitle, localize: true
field :program_notes, type: String, localize: true
field :actor_notes, type: String, localize: true
field :video_notes, type: String, localize: true
field :video_external_link, type: String
field :episodes, type: String
field :create_user_id
field :update_user_id
field :postdate , :type => DateTime, :default => Time.now
field :deadline , :type => DateTime
has_many :video_program_links, :autosave => true, :dependent => :destroy
has_many :video_program_files, :autosave => true, :dependent => :destroy
has_many :video_program_carousel_images, :autosave => true, :dependent => :destroy
accepts_nested_attributes_for :video_program_files, :allow_destroy => true
accepts_nested_attributes_for :video_program_links, :allow_destroy => true
accepts_nested_attributes_for :video_program_carousel_images, :allow_destroy => true
has_and_belongs_to_many :albums
accepts_nested_attributes_for :albums, :allow_destroy => true
scope :open_in_future, ->{where(:is_hidden.ne=>true,:postdate.gt=>Time.now).order(postdate: :asc)}
scope :can_display_and_sorted, ->{where(:is_hidden.ne=>true).valid_time_range.order(postdate: :desc)}
scope :can_display_and_sorted_according_today, ->{where(:is_hidden.ne=>true).order(postdate: :asc).valid_time_range.where(:postdate.gte => Date.today.to_time)}
scope :valid_time_range, ->{and_any_of([{"postdate"=>{"$lte"=> Time.now}, "deadline"=>{"$gte"=> Time.now}}, {"postdate"=>{"$lte"=> Time.now}, "deadline"=>nil}]).order((@manually_sort ? {is_top: :desc,postdate: :desc,id: :desc} : {is_top: :desc,postdate: :desc,id: :desc}))}
scope :is_approved_and_show, ->{where(:approved => true,:is_hidden.ne=>true)}
scope :filter_cats_and_tags, ->(cats,tags) {filter_by_widget_categories(cats,false).filter_by_tags(tags)}
before_save do
if @is_hidden_changed.nil? || @is_hidden_changed != true
@is_hidden_changed = self.is_hidden_changed?
end
end
index({postdate: 1}, { unique: false, background: true })
index({is_top: -1, postdate: -1, _id: -1}, { unique: false, background: true })
index({is_hidden: 1, is_top: -1, postdate: -1, _id: -1, deadline: -1}, { unique: false, background: true })
def update_user
User.find(update_user_id) rescue nil
end
def update_user=(user)
self.update_user_id = user.id
end
def expired?
(self.deadline < Time.now) rescue false
end
def carousel_image_width
(self.custom_carousel_image_width.blank? ? nil : self.custom_carousel_image_width)
end
end

View File

@ -0,0 +1,15 @@
# encoding: utf-8
class VideoProgramCarouselImage
include Mongoid::Document
include Mongoid::Timestamps
mount_uploader :file, AssetUploader
field :description, localize: true
belongs_to :video_programs
def description_text
Nokogiri::HTML(self.description.to_s).css("body").text() rescue ""
end
end

View File

@ -0,0 +1,47 @@
# encoding: utf-8
class VideoProgramFile
include Mongoid::Document
include Mongoid::Timestamps
mount_uploader :file, AssetUploader
field :description, localize: true
field :title, localize: true
field :choose_lang, :type => Array, :default => ["en","zh_tw"]
field :privacy_type, type: String, default: 'public'
belongs_to :video_program
def self.to_fronted(locale=I18n.locale)
self.all.map{|file| file.to_fronted(locale)}.compact rescue []
end
def to_fronted(locale=I18n.locale)
file = self
(file.enabled_for?(locale) && !file[:file].blank?) ? { "file_url" => "/xhr/video_program/file/#{file.id}/#{file['file']}" + "\" title=\"#{file.file_title}",
"file_title" => (file.title.blank? ? URI.unescape(File.basename(file.file.path)) : file.title rescue '')
} : nil rescue nil
end
def file_title
if self.description.present?
return self.description
elsif self.title.present?
return self.title
else
return File.basename(self.file.path)
end
end
def enabled_for?(lang)
if lang.nil?
return true
else
return self.choose_lang.include?(lang)
end
end
def can_access?(user)
if user.nil? && self.privacy_type == 'logged_in'
return false
else
return true
end
end
end

View File

@ -0,0 +1,25 @@
# encoding: utf-8
require 'uri'
class VideoProgramLink
include Mongoid::Document
include Mongoid::Timestamps
field :url
field :title, localize: true
belongs_to :video_program
before_validation :add_http
validates :url, :presence => true, :format => /\A(http|https):\/\/(([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5})|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(:[0-9]{1,5})?(\/.*)?\Z/i
protected
def add_http
unless self.url[/^http:\/\//] || self.url[/^https:\/\//]
self.url = 'http://' + self.url
end
end
end

0
app/views/.keep Normal file
View File

View File

@ -0,0 +1,499 @@
<% content_for :page_specific_css do %>
<%= stylesheet_link_tag "lib/main-forms" %>
<%= stylesheet_link_tag "lib/fileupload" %>
<%= stylesheet_link_tag "lib/main-list" %>
<% end %>
<% content_for :page_specific_javascript do %>
<%= javascript_include_tag "lib/bootstrap-fileupload" %>
<%= javascript_include_tag "lib/bootstrap-datetimepicker" %>
<%= javascript_include_tag "lib/datetimepicker/datetimepicker.js" %>
<%= javascript_include_tag "lib/file-type" %>
<%= javascript_include_tag "lib/module-area" %>
<%= javascript_include_tag "form" %>
<% end %>
<!-- Input Area -->
<div class="input-area">
<!-- Module Tabs -->
<div class="nav-name"><strong><%= t(:module) %></strong></div>
<ul class="nav nav-pills module-nav">
<li class="active"><a href="#basic" data-toggle="tab"><%= t(:basic) %></a></li>
<% if @current_user.is_admin? || @current_user.is_manager?(@module_app) %>
<li><a href="#status" data-toggle="tab"><%= t(:status) %></a></li>
<% end %>
<li><a href="#tag" data-toggle="tab"><%= t(:tags) %></a></li>
<li>
<a href="#video_imageupload" data-toggle="tab"><%= t('video_program.video_image') %></a>
</li>
<li>
<a href="#imageupload" data-toggle="tab"><%= t('video_program.image') %></a>
</li>
<li>
<a href="#carousel_image_upload" data-toggle="tab" title="<%= t('video_program.carousel_image_title') %>"><%= t('video_program.carousel_image') %></a>
</li>
<li>
<a href="#episodes_albums" data-toggle="tab" title="<%= t('video_program.episodes_albums') %>"><%= t('video_program.episodes_albums') %></a>
</li>
</ul>
<!-- Module -->
<div class="tab-content module-area">
<!-- Basic Module -->
<div class="tab-pane fade in active" id="basic">
<!-- Category -->
<div class="control-group">
<label class="control-label muted"><%= t(:category) %></label>
<div class="controls">
<%= select_category(f, @module_app) %>
</div>
</div>
<div class="control-group">
<label class="control-label muted"><%= t("video_program.start_date") %></label>
<div class="controls">
<%= f.datetime_picker :postdate, :no_label => true, :new_record => @video_program.new_record?, :data=>{"picker-type" => "range", "range" => "start"} %>
</div>
</div>
<div class="control-group">
<label class="control-label muted"><%= t("video_program.end_date") %></label>
<div class="controls">
<%= f.datetime_picker :deadline, :no_label => true, :new_record => @video_program.new_record?, :data=>{"picker-type" => "range", "range" => "end"} %>
</div>
</div>
<div class="control-group" id="external_link_box">
<%= f.label :video_external_link, t("video_program.video_external_link"), :class => "control-label muted" %>
<div class="controls">
<%= f.text_field :video_external_link %>
</div>
</div>
<div class="control-group" id="episodes_box">
<%= f.label :episodes, t("video_program.episodes"), :class => "control-label muted" %>
<div class="controls">
<%= f.number_field :episodes %>
</div>
</div>
</div>
<!-- Status Module -->
<% if @current_user.is_admin? || @current_user.is_manager?(@module_app) %>
<div class="tab-pane fade" id="status">
<!-- Status -->
<div class="control-group">
<label class="control-label muted"><%= t(:status) %></label>
<div class="controls" data-toggle="buttons-checkbox">
<label class="checkbox btn <%= 'active' if @video_program.is_top? %>">
<%= f.check_box :is_top %> <%= t(:top) %>
</label>
<label class="checkbox inline btn <%= 'active' if @video_program.is_hot? %>">
<%= f.check_box :is_hot %> <%= t(:hot) %>
</label>
<label class="checkbox inline btn <%= 'active' if @video_program.is_hidden? %>">
<%= f.check_box :is_hidden %> <%= t(:hide) %>
</label>
</div>
</div>
<div class="control-group <%= @video_program.is_top? || (!@video_program.top_end_date.nil? && @video_program.top_end_date > Time.now) ? "" : "hide" %>" data-for="is_top">
<label for="" class="control-label muted">Top end time</label>
<div class="controls">
<%= f.datetime_picker :top_end_date, :no_label => true, :new_record => @video_program.new_record? %>
</div>
</div>
</div>
<% end %>
<!-- Tag Module -->
<div class="tab-pane fade" id="tag">
<div class="control-group">
<label class="control-label muted"><%= t(:tags) %></label>
<%= select_tags(f, @module_app) %>
</div>
</div>
<!-- Images Module -->
<div class="tab-pane fade" id="video_imageupload">
<div class="control-group">
<%= f.label :display_video_image, t("video_program.display_video_image"), :class => "control-label muted" %>
<div class="controls">
<%= f.check_box :display_video_image %>
</div>
</div>
<!-- Images Upload -->
<div class="control-group">
<label class="control-label muted"><%= t(:image) %></label>
<div class="controls">
<div class="fileupload fileupload-new clearfix <%= 'fileupload-edit' if @video_program.video_image.file %>" data-provides="fileupload">
<div class="fileupload-new thumbnail pull-left">
<% if @video_program.video_image.file %>
<%= image_tag @video_program.video_image %>
<% else %>
<img src="/assets/video_program/AAAAAA.png" />
<% end %>
</div>
<div class="fileupload-preview fileupload-exists thumbnail pull-left"></div>
<span class="btn btn-file">
<span class="fileupload-new"><%= t(:select_image) %></span>
<span class="fileupload-exists"><%= t(:change) %></span>
<%= f.file_field :video_image %>
</span>
<a href="#" class="btn fileupload-exists" data-dismiss="fileupload"><%= t(:cancel) %></a>
<div class="controls" data-toggle="buttons-checkbox">
<label class="checkbox inline btn btn-danger fileupload-remove">
<%= f.check_box :remove_video_image %><%= t(:remove) %>
</label>
</div>
</div>
</div>
</div>
<% @site_in_use_locales.each do |locale| %>
<%= f.fields_for :video_image_description_translations do |f| %>
<div class="control-group">
<label class="control-label muted" for="image_description_<%= locale.to_s %>"><%= t(:description) + " (#{t(locale.to_s)})" %></label>
<div class="controls">
<%= f.text_field locale, value: (@video_program.video_image_description_translations[locale.to_s] rescue nil) %>
</div>
</div>
<% end %>
<% end %>
</div>
<!-- Images Module -->
<div class="tab-pane fade" id="imageupload">
<div class="control-group">
<%= f.label :display_image, t("video_program.display_image"), :class => "control-label muted" %>
<div class="controls">
<%= f.check_box :display_image %>
</div>
</div>
<!-- Images Upload -->
<div class="control-group">
<label class="control-label muted"><%= t(:image) %></label>
<div class="controls">
<div class="fileupload fileupload-new clearfix <%= 'fileupload-edit' if @video_program.image.file %>" data-provides="fileupload">
<div class="fileupload-new thumbnail pull-left">
<% if @video_program.image.file %>
<%= image_tag @video_program.image %>
<% else %>
<img src="/assets/video_program/AAAAAA.png" />
<% end %>
</div>
<div class="fileupload-preview fileupload-exists thumbnail pull-left"></div>
<span class="btn btn-file">
<span class="fileupload-new"><%= t(:select_image) %></span>
<span class="fileupload-exists"><%= t(:change) %></span>
<%= f.file_field :image %>
</span>
<a href="#" class="btn fileupload-exists" data-dismiss="fileupload"><%= t(:cancel) %></a>
<div class="controls" data-toggle="buttons-checkbox">
<label class="checkbox inline btn btn-danger fileupload-remove">
<%= f.check_box :remove_image %><%= t(:remove) %>
</label>
</div>
</div>
</div>
</div>
<% @site_in_use_locales.each do |locale| %>
<%= f.fields_for :image_description_translations do |f| %>
<div class="control-group">
<label class="control-label muted" for="image_description_<%= locale.to_s %>"><%= t(:description) + " (#{t(locale.to_s)})" %></label>
<div class="controls">
<%= f.text_field locale, value: (@video_program.image_description_translations[locale.to_s] rescue nil) %>
</div>
</div>
<% end %>
<% end %>
</div>
<div class="tab-pane fade" id="carousel_image_upload">
<div class="control-group">
<label class="control-label muted" for="carousel_image_width"><%= t("video_program.carousel_image_width") %></label>
<div class="controls">
<%= f.text_field :custom_carousel_image_width, :placeholder => t("video_program.custom_carousel_image_width_hint") %>
</div>
</div>
<% if !f.object.video_program_carousel_images.blank? %>
<div class="exist">
<% f.object.video_program_carousel_images.each_with_index do |video_program_carousel_image, i| %>
<%= f.fields_for :video_program_carousel_images, video_program_carousel_image do |f| %>
<%= render :partial => 'form_image', :object => video_program_carousel_image, :locals => {:f => f, :i => i} %>
<% end %>
<% end %>
<hr>
</div>
<% end %>
<!-- Add -->
<div class="add-target">
</div>
<p class="add-btn controls">
<%= hidden_field_tag 'bulletin_carousel_image_count', f.object.video_program_carousel_images.count %>
<a id="add_carousel_image" class="trigger btn btn-small btn-primary"><i class="icons-plus"></i> <%= t(:add) %></a>
</p>
</div>
<div class="tab-pane fade" id="episodes_albums">
<%= render partial: 'admin/galleries/select_albums_form', locals: {field: 'video_program[album_ids][]', albums: f.object.albums} %>
</div>
</div>
<!-- Language Tabs -->
<div class="nav-name"><strong><%= t(:language) %></strong></div>
<ul class="nav nav-pills language-nav">
<% @site_in_use_locales.each_with_index do |locale, i| %>
<li class="<%= 'active' if i == 0 %>">
<a data-toggle="tab" href=".<%= locale %>"><%= t(locale) %></a>
</li>
<% end %>
</ul>
<!-- Language -->
<div class="tab-content language-area">
<% @site_in_use_locales.each_with_index do |locale, i| %>
<div class="<%= locale %> tab-pane fade <%= ( i == 0 ) ? "in active" : '' %>">
<div class="control-group input-title">
<label class="control-label muted"><%= t('video_program.title') %></label>
<div class="controls">
<%= f.fields_for :title_translations do |f| %>
<%= f.text_area locale, class: "ckeditor_reduce input-block-level", placeholder: t('video_program.title'), value: (@video_program.title_translations[locale] rescue nil) %>
<% end %>
</div>
</div>
<div class="control-group input-subtitle">
<label class="control-label muted"><%= t(:subtitle) %></label>
<div class="controls">
<div class="textarea">
<%= f.fields_for :subtitle_translations do |f| %>
<%= f.text_area locale, rows: 2, class: "ckeditor input-block-level", value: (@video_program.subtitle_translations[locale] rescue nil) %>
<% end %>
</div>
</div>
</div>
<div class="control-group input-notes">
<label class="control-label muted"><%= t("video_program.program_notes") %></label>
<div class="controls">
<div class="textarea">
<%= f.fields_for :program_notes_translations do |f| %>
<%= f.cktext_area locale, rows: 5, class: "input-block-level", :value => (@video_program.program_notes_translations[locale] rescue nil) %>
<% end %>
</div>
</div>
</div>
<div class="control-group input-notes">
<label class="control-label muted"><%= t("video_program.actor_notes") %></label>
<div class="controls">
<div class="textarea">
<%= f.fields_for :actor_notes_translations do |f| %>
<%= f.cktext_area locale, rows: 5, class: "input-block-level", :value => (@video_program.actor_notes_translations[locale] rescue nil) %>
<% end %>
</div>
</div>
</div>
<div class="control-group input-notes">
<label class="control-label muted"><%= t("video_program.video_notes") %></label>
<div class="controls">
<div class="textarea">
<%= f.fields_for :video_notes_translations do |f| %>
<%= f.cktext_area locale, rows: 5, class: "input-block-level", :value => (@video_program.video_notes_translations[locale] rescue nil) %>
<% end %>
</div>
</div>
</div>
</div>
<% end %>
<!-- Link -->
<div class="control-group">
<label class="control-label muted"><%= t(:link) %></label>
<div class="controls add-input">
<!-- Exist -->
<% if @video_program && !@video_program.video_program_links.blank? %>
<div class="exist">
<% @video_program.video_program_links.each_with_index do |video_program_link, i| %>
<%= f.fields_for :video_program_links, video_program_link do |f| %>
<%= render :partial => 'form_link', :object => video_program_link, :locals => {:f => f, :i => i} %>
<% end %>
<% end %>
<hr>
</div>
<% end %>
<!-- Add -->
<div class="add-target">
</div>
<p class="add-btn">
<%= hidden_field_tag 'video_program_link_field_count', @video_program.video_program_links.count %>
<a id="add_link" class="trigger btn btn-small btn-primary"><i class="icons-plus"></i> <%= t(:add) %></a>
</p>
</div>
</div>
<!-- File -->
<div class="control-group">
<label class="control-label muted"><%= t(:file_) %></label>
<div class="controls">
<!-- Exist -->
<% if @video_program && !@video_program.video_program_files.blank? %>
<div class="exist">
<% @video_program.video_program_files.each_with_index do |video_program_file, i| %>
<%= f.fields_for :video_program_files, video_program_file do |f| %>
<%= render :partial => 'form_file', :object => video_program_file, :locals => {:f => f, :i => i} %>
<% end %>
<% end %>
<hr>
</div>
<% end %>
<!-- Add -->
<div class="add-target">
</div>
<p class="add-btn">
<%= hidden_field_tag 'video_program_file_field_count', @video_program.video_program_files.count %>
<a id="add_file" class="trigger btn btn-small btn-primary"><i class="icons-plus"></i> <%= t(:add) %></a>
</p>
</div>
</div>
</div>
</div>
<!-- Form Actions -->
<div class="form-actions">
<%= get_referer_url[:action] rescue "" %>
<%= f.submit t('submit'), class: 'btn btn-primary' %>
<input type="hidden" name="referer_url" value="<%= get_referer_url %>">
<%= button_tag t("preview"), id: "button_for_preview", name: "commit", class: 'btn', type: :button %>
<%= link_to t('cancel'), admin_video_programs_path, :class=>"btn" %>
</div>
<span id='show_preview'>
<div class="modal hide fade in banner-preview" id="">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3><%= t(:preview) %></h3>
</div>
<div class="modal-body">
<iframe id="preview-iframe" src=""></iframe>
</div>
<div class="modal-footer">
<a href="#" class="btn" data-dismiss="modal"><%= t(:close) %></a>
</div>
</div>
</span>
<% if !@module_app.tags.empty? %>
<script type="text/javascript">
$("form.previewable").on("submit", function(){
if(!$("input[name='video_program[tags][]']").is(":checked")){
if(!confirm("You have selected no tag, do you wish to continue?")){
return false;
}
}
})
</script>
<% end %>
<script>
$("#video_program_display_image").click(function(){$("#image_display_setting").toggleClass("hide")})
function Appendzero(obj)
{
if(obj<10) return "0" +""+ obj;
else return obj;
}
$(function() {
if (location.pathname.substr(-3)=='new'){
var getDate = new Date();
var toDay = getDate.getFullYear()+"/"+ (Appendzero(getDate.getMonth()+1))+"/"+Appendzero(getDate.getDate())+" "+Appendzero(getDate.getHours())+":"+Appendzero(getDate.getMinutes());
$('input[name="video_program[postdate]"]').val(toDay);
}
$("#main-wrap").after("");
$(document).on('click', '#add_link', function(){
var new_id = $(this).prev().attr('value');
var old_id = new RegExp("new_video_program_links", "g");
var on = $('.language-nav li.active').index();
var le = $(this).parent('.add-btn').prev('.add-target').children('.start-line').length;
$(this).prev().attr('value', parseInt(new_id) + 1);
$(this).parent().siblings('.add-target').append(("<%= escape_javascript(add_attribute 'form_link', f, :video_program_links) %>").replace(old_id, new_id));
$(this).parent('.add-btn').prev('.add-target').children('.start-line').eq(le).children('.tab-content').children('.tab-pane').eq(on).addClass('in active').siblings().removeClass('in active');
formTip();
});
$(document).on('click', '#add_file', function(){
var new_id = $(this).prev().attr('value');
var old_id = new RegExp("new_video_program_files", "g");
var on = $('.language-nav li.active').index();
var le = $(this).parent('.add-btn').prev('.add-target').children('.start-line').length;
$(this).prev().attr('value', parseInt(new_id) + 1);
$(this).parent().siblings('.add-target').append(("<%= escape_javascript(add_attribute 'form_file', f, :video_program_files) %>").replace(old_id, new_id));
$(this).parent('.add-btn').prev('.add-target').children('.start-line').eq(le).children('.input-append').find('.tab-content').each(function() {
$(this).children('.tab-pane').eq(on).addClass('in active').siblings().removeClass('in active');
});
formTip();
});
$(document).on('click', '#add_carousel_image', function(){
var new_id = $(this).prev().attr('value');
var old_id = new RegExp("new_video_program_carousel_images", "g");
var on = $('.language-nav li.active').index();
var le = $(this).parent('.add-btn').prev('.add-target').children('.start-line').length;
$(this).prev().attr('value', parseInt(new_id) + 1);
$(this).parent().siblings('.add-target').append(("<%= escape_javascript(add_attribute 'form_image', f, :video_program_carousel_images) %>").replace(old_id, new_id));
$(this).parent('.add-btn').prev('.add-target').children('.start-line').eq(le).children('.input-append').find('.tab-content').each(function() {
$(this).children('.tab-pane').eq(on).addClass('in active').siblings().removeClass('in active');
});
});
$(document).on('click', '.fileupload-remove', function(){
if($(this).find(".delete_image").length != 0){
$(this).parents('.image_group').remove();
}
});
$(document).on('click', '.delete_link', function(){
$(this).parents('.input-prepend').remove();
});
$(document).on('click', '.delete_file', function(){
$(this).parents('.input-prepend').remove();
});
$(document).on('click', '.remove_existing_record', function(){
if(confirm("<%= I18n.t(:sure?)%>")){
$(this).children('.should_destroy').attr('value', 1);
$(this).parents('.start-line').hide();
}
});
$('#remind-check').prop('checked') ? '':$('.content-box').addClass('hide')
$('#remind-check').on('change', function() {
$(this).prop('checked') ? $('.content-box').removeClass('hide'):$('.content-box').addClass('hide')
})
$("#video_program_is_top").parent().on("click",function(){
setTimeout(function(){
if($("#video_program_is_top").parent().hasClass("active")){
$("div[data-for=is_top]").removeClass("hide");
}else{
$("div[data-for=is_top]").addClass("hide");
$("div[data-for=is_top]").find("input[type=text]").val("");
}
},100)
})
});
</script>

View File

@ -0,0 +1,69 @@
<% if form_file.new_record? %>
<div class="fileupload fileupload-new start-line" data-provides="fileupload">
<% else %>
<div class="fileupload fileupload-exists start-line" data-provides="fileupload">
<% if form_file.file.blank? %>
<%= t(:no_file) %>
<% else %>
<%= link_to content_tag(:i) + form_file.file_identifier, form_file.file.url, {:class => 'file-link file-type', :target => '_blank', :title => form_file.file_identifier} %>
<% end %>
<% end %>
<div class="input-prepend input-append">
<label>
<span class="add-on btn btn-file" title='<%= t(:file_) %>'>
<i class="icons-paperclip"></i>
<%= f.file_field :file %>
</span>
<div class="uneditable-input input-medium">
<i class="icon-file fileupload-exists"></i>
<span class="fileupload-preview"><%= (form_file.new_record? || form_file.file.blank?) ? t(:select_file) : t(:change_file) %></span>
</div>
</label>
<span class="add-on icons-pencil" title='<%= t(:alternative) %>'></span>
<span class="tab-content">
<% @site_in_use_locales.each_with_index do |locale, i| %>
<span class="tab-pane fade <%= ( i == 0 ) ? "in active" : '' %> <%= locale %>">
<%= f.fields_for :title_translations do |f| %>
<%= f.text_field locale, :class => "input-medium", placeholder: t(:alternative), :value => (form_file.title_translations[locale] rescue nil) %>
<% end %>
</span>
<% end %>
</span>
<span class="add-on icons-pencil" title='<%= t(:description) %>'></span>
<span class="tab-content">
<% @site_in_use_locales.each_with_index do |locale, i| %>
<span class="tab-pane fade <%= ( i == 0 ) ? "in active" : '' %> <%= locale %>">
<%= f.fields_for :description_translations do |f| %>
<%= f.text_field locale, :class => "input-medium", placeholder: t(:description), :value => (form_file.description_translations[locale] rescue nil) %>
<% end %>
</span>
<% end %>
</span>
</span>
<span class="add-on btn-group btn" title="<%= t('archive.show_lang') %>">
<i class="icons-earth"></i> <span class="caret"></span>
<ul class="dropdown-menu">
<% @site_in_use_locales.each do |locale| %>
<li>
<label class="checkbox">
<%= check_box_tag "video_program[video_program_files_attributes][#{( form_file.new_record? ? 'new_video_program_files' : "#{i}" )}][choose_lang][]", locale, form_file.choose_lang.include?(locale.to_s) %>
<%= t(locale.to_s) %>
</label>
</li>
<% end %>
</ul>
<%= hidden_field_tag "video_program[video_program_files_attributes][#{( form_file.new_record? ? 'new_video_program_files' : "#{i}" )}][choose_lang][]", '' %>
</span>
<% if form_file.new_record? %>
<span class="delete_file add-on btn" title="<%= t(:delete_) %>">
<a class="icon-trash"></a>
</span>
<% else %>
<span class="remove_existing_record add-on btn" title="<%= t(:remove) %>">
<%= f.hidden_field :id %>
<a class="icon-remove"></a>
<%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %>
</span>
<% end %>
</div>
</div>

View File

@ -0,0 +1,49 @@
<!-- Images Upload -->
<div class="image_group">
<div class="control-group">
<label class="control-label muted"><%= t(:image) %></label>
<div class="controls">
<div class="fileupload fileupload-new clearfix <%= 'fileupload-edit' if form_image.file.present? %>" data-provides="fileupload">
<div class="fileupload-new thumbnail pull-left">
<% if form_image.file.file %>
<%= image_tag form_image.file %>
<% else %>
<img src="/assets/video_program/AAAAAA.png" />
<% end %>
</div>
<div class="fileupload-preview fileupload-exists thumbnail pull-left"></div>
<span class="btn btn-file">
<span class="fileupload-new"><%= t(:select_image) %></span>
<span class="fileupload-exists"><%= t(:change) %></span>
<%= f.file_field :file %>
</span>
<a href="#" class="btn fileupload-exists" data-dismiss="fileupload"><%= t(:cancel) %></a>
<div class="controls" data-toggle="buttons-checkbox">
<label class="checkbox inline btn btn-danger fileupload-remove">
<% if form_image.new_record? %>
<span class="delete_file delete_image add-on" title="<%= t(:delete_) %>">
<%= t(:delete_) %>
</span>
<% else %>
<span class="remove_existing_record add-on" title="<%= t(:remove) %>">
<%= f.hidden_field :id %>
<%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %>
<%= t(:remove) %>
</span>
<% end %>
</label>
</div>
</div>
</div>
</div>
<% @site_in_use_locales.each do |locale| %>
<%= f.fields_for :description_translations do |f| %>
<div class="control-group">
<label class="control-label muted" for="image_description_<%= locale.to_s %>"><%= t(:description) + " (#{t(locale.to_s)})" %></label>
<div class="controls">
<%= f.text_field locale, value: (form_image.description_translations[locale.to_s] rescue nil) %>
</div>
</div>
<% end %>
<% end %>
</div>

View File

@ -0,0 +1,26 @@
<div class="input-prepend input-append start-line">
<span class="add-on icons-link" title="<%= t(:url) %>"></span>
<%= f.text_field :url, class: "input-large", placeholder: t(:url) %>
<span class="add-on icons-pencil" title="<%= t(:url_alt) %>"></span>
<span class="tab-content">
<% @site_in_use_locales.each_with_index do |locale, i| %>
<span class="tab-pane fade <%= ( i == 0 ) ? "in active" : '' %> <%= locale %>">
<%= f.fields_for :title_translations do |f| %>
<%= f.text_field locale, :class => "input-large", placeholder: t(:url_alt), :value => (form_link.title_translations[locale] rescue nil) %>
<% end %>
</span>
<% end %>
</span>
<% if form_link.new_record? %>
<span class="delete_link add-on btn" title="<%= t(:delete_) %>">
<a class="icon-trash"></a>
</span>
<% else %>
<span class="remove_existing_record add-on btn" title="<%= t(:remove) %>">
<%= f.hidden_field :id %>
<a class="icon-remove"></a>
<%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %>
</span>
<% end %>
</div>

View File

@ -0,0 +1,70 @@
<table class="table main-list">
<thead>
<tr class="sort-header">
<% @table_fields.each do |f| %>
<%= thead(f) %>
<% end %>
</tr>
</thead>
<tbody>
<% @video_programs.each do |video_program| %>
<tr>
<td>
<%= video_program.status_for_table %>
</td>
<td>
<%= video_program.category.title rescue "" %>
<% if (video_program.category.disable rescue false) %>
<span class='label'><%= t(:disabled) %></span>
<% end %>
</td>
<td>
<% if video_program.expired? || (video_program.category.disable rescue false)%>
<%= video_program.title.to_s.html_safe %>
<% else %>
<a href="<%= OrbitHelper.cal_url_to_show(@module_app, video_program) %>" target="_blank"><%= video_program.title.to_s.html_safe %></a>
<% end %>
<% if video_program.expired? %>
<span class='label'><%= t(:expired) %></span>
<% end %>
<div class="quick-edit">
<ul class="nav nav-pills">
<li><a href="#" class="detail-row" onclick="$('#<%= "#{video_program.id.to_s}-detail" %>').slideToggle(300); return false;"><%= t(:detail) %></a></li>
<% if can_edit_or_delete?(video_program) %>
<li><a href="<%= edit_admin_video_program_path(video_program.id) %>"><%= t(:edit) %></a></li>
<li><a href="#" class="delete text-error" rel="<%= admin_video_program_path(video_program.id) %>"><%= t(:delete_) %></a></li>
<% end %>
</ul>
</div>
</td>
<td><%= format_value video_program.postdate %></td>
<td class="<%= video_program.expired? ? "expired" : "" %>"><%= format_value video_program.deadline %></td>
<td><%= video_program.update_user.user_name rescue ""%></td>
</tr>
<tr class="footable-row-detail">
<td class="footable-cell-detail" colspan="6">
<div id="<%= "#{video_program.id.to_s}-detail" %>" class="footable-row-detail-inner" style="display: none;">
<div>
<strong><%= t(:view_count) %></strong> :
<span class="label label-info"><%= video_program.view_count %></span>
</div>
<div>
<strong><%= t(:tags) %></strong> :
<% video_program.tags.each do |tag| %>
<span class="label label-warning"><%= tag.name %></span>
<% end %>
</div>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
<%=
content_tag :div, class: "bottomnav clearfix" do
content_tag(:div, paginate(@video_programs), class: "pagination pagination-centered") +
content_tag(:div, link_to(t(:new_),new_admin_video_program_path, :class=>"btn btn-primary"), class: "pull-right")
end
%>

View File

@ -0,0 +1,5 @@
<%= form_for @video_program, url: admin_video_program_path(@video_program), html: {class: "form-horizontal main-forms previewable"} do |f| %>
<fieldset>
<%= render :partial => 'form', locals: {f: f} %>
</fieldset>
<% end %>

View File

@ -0,0 +1,6 @@
<%= render_filter @filter_fields, "index_table" %>
<span id="index_table">
<%= render 'index'%>
</span>
<%= render 'layouts/delete_modal', delete_options: @delete_options %>

View File

@ -0,0 +1,5 @@
<%= form_for @video_program, url: admin_video_programs_path, html: {class: "form-horizontal main-forms previewable"} do |f| %>
<fieldset>
<%= render :partial => 'form', locals: {f: f} %>
</fieldset>
<% end %>

View File

@ -0,0 +1 @@
<%= render_view %>

View File

@ -0,0 +1,116 @@
<%
data = action_data
%>
<style type="text/css">
.carousel_images_slide {
padding: 0 2.5em;
}
</style>
<%= render_view %>
<script>
(function($) {
function calculate_video_carousel(skip_images_slide)
{
var cycle_slideshow = $(".carousel_images .cycle-slideshow");
var video_carousel_slide = $(".video_program_carousel_slide");
var carousel_images_slide = $('.carousel_images_slide');
if (!skip_images_slide) {
var carousel_images_slide_first_child = carousel_images_slide.find(">li").eq(window.active_slide);
if(carousel_images_slide_first_child.length > 0){
var content_size = Math.floor((carousel_images_slide.outerWidth() - Number.parseInt(carousel_images_slide.css('font-size')) * 3) / carousel_images_slide_first_child.outerWidth(true));
content_size = Math.max(content_size,1);
carousel_images_slide.find(">li").css("display","none");
var active_count = carousel_images_slide.find(">li").length - window.active_slide;
if(active_count < content_size){
window.active_slide -= (content_size - active_count);
}
window.active_slide = Math.max(window.active_slide,0);
for(var i = window.active_slide; i < window.active_slide + content_size;i++){
carousel_images_slide.find(">li").eq(i).css("display","block");
}
}
}
cycle_slideshow.cycle('pause');
var carousel_image_block_width = $('.carousel_images').width();
video_carousel_slide.css('height', '');
var heights = video_carousel_slide.map(function(i,v){
return $(v).height() * carousel_image_block_width / $(v).width();
})
var max_height = Math.max.apply(null,heights);
video_carousel_slide.each(function(i,v){
$(v).height(max_height);
})
cycle_slideshow.cycle('resume');
}
$("img[src='']").remove();
$('.pause-slide').click(function(){
$(this).parent("ul").parent('.w-ba-banner').find(".cycle-slideshow").cycle('pause');
$(this).addClass('active');
$(this).parents('.carousel_images').find('.resume-slide').removeClass('active');
});
$('.resume-slide').click(function(){
$(this).parent("ul").parent('.w-ba-banner').find(".cycle-slideshow").cycle('resume');
$(this).addClass('active');
$(this).parents('.carousel_images').find('.pause-slide').removeClass('active');
});
$('.next-button').off('click').on('click',function(){
$(this).parent("ul").parent('.w-ba-banner').find(".cycle-slideshow").cycle("next");
})
$('.prev-button').off('click').on('click',function(){
$(this).parent("ul").parent('.w-ba-banner').find(".cycle-slideshow").cycle("prev");
})
window.active_slide = 0;
$('.prev_img').off('click').on('click',function(){
var carousel_images_slide = $('.carousel_images_slide');
var carousel_images_slide_first_child = carousel_images_slide.find(">li").eq(window.active_slide);
if(carousel_images_slide_first_child.length > 0){
var content_size = Math.floor((carousel_images_slide.outerWidth() - Number.parseInt(carousel_images_slide.css('font-size')) * 3) / carousel_images_slide_first_child.outerWidth(true));
content_size = Math.max(content_size,1);
if(carousel_images_slide.find(">li").length > content_size && window.active_slide > 0){
window.active_slide -= content_size;
window.active_slide = Math.max(window.active_slide, 0);
carousel_images_slide.find(">li").css("display","none");
for(var i = window.active_slide; i < window.active_slide + content_size;i++){
carousel_images_slide.find(">li").eq(i).css("display","block");
}
}
}
})
$('.next_img').off('click').on('click',function(){
var carousel_images_slide = $('.carousel_images_slide');
var carousel_images_slide_first_child = carousel_images_slide.find(">li").eq(window.active_slide);
if(carousel_images_slide_first_child.length > 0){
var content_size = Math.floor((carousel_images_slide.outerWidth() - Number.parseInt(carousel_images_slide.css('font-size')) * 3) / carousel_images_slide_first_child.outerWidth(true));
content_size = Math.max(content_size,1);
var li_length = carousel_images_slide.find(">li").length;
if(li_length > content_size && (window.active_slide + content_size) < li_length){
window.active_slide += content_size;
window.active_slide = Math.min(window.active_slide,li_length - 1);
carousel_images_slide.find(">li").css("display","none");
for(var i = window.active_slide; i < window.active_slide + content_size;i++){
carousel_images_slide.find(">li").eq(i).css("display","block");
}
}
}
})
$(".carousel_img_item img").off("click").on("click",function(){
$(".carousel_images .cycle-slideshow").cycle($(this).index(".carousel_img_item img"));
})
$(document).ready(function(){
calculate_video_carousel();
$('.carousel_images .resume-slide').addClass('active');
$('.cycle-slideshow').on('cycle-after',function(ev, opts, old_el, new_el){
$(".active_slide").text($(new_el).index());
})
})
$(window).on("load",function(){
calculate_video_carousel();
})
$(window).resize(function(){
calculate_video_carousel();
})
}(jQuery));
</script>

18
bin/rails Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env ruby
# This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
ENGINE_ROOT = File.expand_path('../..', __FILE__)
ENGINE_PATH = File.expand_path('../../lib/video_programs/engine', __FILE__)
# Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
# require 'rails/all'
# require 'rails/engine/commands'
require "action_controller/railtie"
require "action_mailer/railtie"
require "sprockets/railtie"
require "rails/test_unit/railtie"
require 'rails/engine/commands'
require "mongoid/railtie"

23
config/locales/en.yml Normal file
View File

@ -0,0 +1,23 @@
en:
module_name:
video_program: Video Program
video_program:
title: Video Title
display_video_image: Display Video Logo
video_image: Video Logo
display_image: Display Cover Image
image: Cover Image
episodes: Episodes
episodes_text: "%{num} Episodes"
episodes_albums: Episodes Introduction
carousel_image: Stage Photo
carousel_image_title: Stage Photo(display at the bottom of show page)
carousel_image_width: Stage Photo Width
custom_carousel_image_width_hint: "If blank, width will be default value."
program_notes: Program Introduction
actor_notes: Actor Introduction
video_notes: Video Introduction
start_date: Start Date
end_date: End Date
video_external_link: Video External Link
play: Play

23
config/locales/zh_tw.yml Normal file
View File

@ -0,0 +1,23 @@
zh_tw:
module_name:
video_program: 影片節目
video_program:
title: 影片名稱
display_video_image: 顯示影片Logo
video_image: 影片Logo
display_image: 顯示封面圖片
image: 封面圖片
episodes: 集數
episodes_text: "全 %{num} 集"
episodes_albums: 分集介紹
carousel_image: 劇照
carousel_image_title: 劇照(在show頁面底部顯示)
carousel_image_width: 劇照寬度
custom_carousel_image_width_hint: "未填寫,則使用預設寬度"
program_notes: 節目介紹
actor_notes: 角色介紹
video_notes: 影片介紹
start_date: 開始日期
end_date: 結束日期
video_external_link: 影片外部連結
play: 前往觀看

21
config/routes.rb Normal file
View File

@ -0,0 +1,21 @@
Rails.application.routes.draw do
locales = Site.first.in_use_locales rescue I18n.available_locales
scope "(:locale)", locale: Regexp.new(locales.join("|")) do
namespace :admin do
resources :video_programs do
collection do
end
end
end
resources :video_programs do
collection do
get ':slug_title-:uid', to: 'video_programs#show', as: :display
end
end
get '/xhr/video_programs/file/:id/*f_name', to: 'video_programs#get_file', format: false
end
end

4
lib/video_programs.rb Normal file
View File

@ -0,0 +1,4 @@
require "video_programs/engine"
module VideoPrograms
end

View File

@ -0,0 +1,49 @@
module VideoPrograms
class Engine < ::Rails::Engine
initializer "video_programs" do
Rails.application.config.to_prepare do
OrbitApp.registration "video_programs", :type => "ModuleApp" do
module_label "module_name.video_program"
base_url File.expand_path File.dirname(__FILE__)
taggable "VideoProgram"
categorizable
authorizable
frontend_enabled
data_count 1..30
side_bar do
head_label_i18n 'module_name.video_program', icon_class: "icons-megaphone"
available_for "users"
active_for_controllers (['admin/video_programs'])
head_link_path "admin_video_programs_path"
context_link 'module_name.video_program',
:link_path=>"admin_video_programs_path" ,
:priority=>1,
:active_for_action=>{'admin/video_programs'=>'index'},
:available_for => 'users'
context_link 'new_',
:link_path=>"new_admin_video_program_path" ,
:priority=>2,
:active_for_action=>{'admin/video_programs'=>'new'},
:available_for => 'sub_managers'
context_link 'categories',
:link_path=>"admin_module_app_categories_path" ,
:link_arg=>"{:module_app_id=>ModuleApp.find_by(:key=>'video_program').id}",
:priority=>3,
:active_for_action=>{'admin/video_programs'=>'categories'},
:active_for_category => 'VideoPrograms',
:available_for => 'managers'
context_link 'tags',
:link_path=>"admin_module_app_tags_path" ,
:link_arg=>"{:module_app_id=>ModuleApp.find_by(:key=>'video_program').id}",
:priority=>4,
:active_for_action=>{'admin/video_programs'=>'tags'},
:active_for_tag => 'VideoPrograms',
:available_for => 'managers'
end
end
end
end
end
end

View File

@ -0,0 +1,3 @@
module VideoPrograms
VERSION = "0.0.1"
end

View File

@ -0,0 +1,36 @@
<div class="index-video-program video-program card-group index1 {{display_class}}">
<h3 class="index-title">
<span>{{page-title}}</span>
</h3>
<link rel="stylesheet" type="text/css" href="/assets/video-program-card.css">
<div class="row" data-level="0" data-list="categories">
<h4 class="category-title">{{category-title}}</h4>
<div class="row" data-level="1" data-list="video-programs">
<div class="card card-flip h-100">
<div class="card-front">
<div class="card-body" style="padding:0;">
<img
src="{{thumb-src}}"
alt="{{title}}"
>
<div class="card-footer">
<h3 class="card-title">{{title}}</h3>
</div>
</div>
</div>
<div class="card-back">
<div class="card-body">
<h3 class="card-title">{{title}}</h3>
{{subtitle}}
<div class="card-button-group">
<a title="{{title}}" href="{{link_to_show}}" class="btn btn-secondary view ">
<i class="fa fa-link" aria-hidden="true"></i>
</a>
<span class="episodes">{{episodes_text}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,15 @@
{
"frontend": [
{
"filename" : "index1",
"name" : {
"zh_tw" : "1. 標準標題列表-1A ( 模組標題, 類別, 狀態, 標題, 日期 )",
"en" : "1. Standard Title List-1 (widget-title, category, status, title, postdate)"
},
"thumbnail" : "event_news_index1_thumbs.png",
"force_cover": "true"
}
],
"widgets" : [
]
}

View File

@ -0,0 +1,148 @@
<style type="text/css">
.btn.disabled {
pointer-events: none;
cursor: default;
background-image: unset;
background-color: #292929;
}
a.play-btn {
padding: 1em 2.5em;
background: #333;
color: #fff;
border-radius: 20em;
font-size: 1em;
}
a.play-btn:hover {
color: #fff;
font-size: 1.1em;
}
.video-description {
margin: 1em 0;
}
.video-information-wrap {
font-size: 1.2em;
}
.video-short-description {
}
.video-cover-image-wrap {
padding: 0 1em;
}
.video-cover-image-wrap img {
border-radius: 5em;
}
.clearfix {
clear: both;
}
.episode_tag {
font-size: 1.2em;
background: none;
color: inherit;
padding-left: 0;
font-weight: normal;
}
.episode_title {
font-size: 1.3em;
font-weight: bolder;
}
.carousel_images{
{{carousel_display_style}}
}
.episode_item {
margin-bottom: 1em;
}
#episodes-head-wrap {
display: flex;
flex-wrap: wrap;
align-items: center;
}
#episodes-head, #episodes_tag_box {
float: left;
vertical-align: middle;
}
#episodes-head {
margin-top: 0.625em;
margin-right: 0.5em;
}
.episodes_albums-list {
padding: 0;
}
@media (max-width: 768px) {
.episode_item {
padding: 0;
}
}
</style>
<article class="s-video-program show-video-program ">
<div class="video-short-description col-md-5 col-xs-12">
{{video_image_html}}
<a target="_blank" href="{{video_external_link}}" class="btn play-btn {{video_external_link_class}}" title="{{play-head}}">
{{play-head}}
<i class="fa fa-play"></i>
</a>
<p class="video-description">{{subtitle}}</p>
<h2 class="s-video-program__show-title">
{{title}}
</h2>
<span class="video-information-wrap">
<span class="s-video-program__tag-wrap s-video-program__meta--item ">
<span data-list="tags" data-level="0">
<a href="{{url}}"><span class="s-video-program__tag label label-default">{{tag}}</span></a>
</span>
</span>
<span class="video-information">{{video_notes}}</span>
</span>
</div>
<div class="video-cover-image-wrap col-md-7 col-xs-12">
{{image_html}}
</div>
<div class="clearfix"></div>
<section class="s-video-program_notes-wrap">
<h3>{{program_notes-head}}</h3>
<p clas="program_notes">
{{program_notes}}
</p>
</section>
<section class="s-video-actor_notes-wrap {{actor_notes_class}}">
<h3>{{actor_notes-head}}</h3>
<p clas="actor_notes">
{{actor_notes}}
</p>
</section>
<section class="s-video-stage-photo-wrap {{carousel_image_class}}">
<h3>{{carousel_image-head}}</h3>
{{video_program_carousel_images}}
</section>
<section class="s-video-episodes_albums-wrap {{episodes_albums_class}}">
<div id="episodes-head-wrap">
<h3 id="episodes-head">{{episodes_albums-head}}</h3>
<select id="episodes_tag_box" data-list="episodes_albums" data-level="0">
<option value="{{tab-index}}">{{images_tag}}</option>
</select>
</div>
<div class="episodes_albums-list-wrap tab-content" data-list="episodes_albums" data-level="0">
<ul class="episodes_albums-list col-sm-12 tab-pane fade {{tab-class}}" data-list="images" data-level="1">
<li class="episode_item col-xs-12 col-sm-4">
<span class="episode_tag label label-default" data-list="img-tags" data-level="2">
{{tag}}
</span>
<div class="clearfix"></div>
<h3 class="episode_title">{{ep_title}}</h3>
<p class="episode_description">{{ep_desc}}</p>
<img src="{{img-src}}" alt="{{ep_title}}">
</li>
</ul>
<div class="clearfix"></div>
</div>
</section>
<script type="text/javascript">
$("#episodes_tag_box").change(function(){
var tab_panes = $(".episodes_albums-list.tab-pane");
tab_panes.removeClass("active in").eq(parseInt($(this).val())).addClass('active in');
})
</script>
</article>
{{link_to_edit}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

29
video_programs.gemspec Normal file
View File

@ -0,0 +1,29 @@
# encoding: UTF-8
$:.push File.expand_path("../lib", __FILE__)
# Maintain your gem's version:
require "video_programs/version"
bundle_update_flag = ARGV[0]=='update' || ARGV[0]=='install'
if bundle_update_flag
env_pwd = ENV['PWD']
app_path = File.expand_path(__dir__)
require ::File.expand_path('app/helpers/bundler_helper.rb', env_pwd)
extend BundlerHelper
puts "copy_template_modules"
copy_template_modules(app_path, 'video_program')
end
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = "video_programs"
s.version = VideoPrograms::VERSION
s.authors = ["Peter Chiu"]
s.email = ["naruto0426@rulingcom.com"]
s.homepage = "http://orbitek.co"
s.summary = "VideoProgram for Orbit"
s.description = "VideoProgram for Orbit"
s.license = "MIT"
s.metadata = {
}
s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"]
end