concerto_template_scheduling 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +13 -0
- data/README.md +24 -0
- data/Rakefile +34 -0
- data/app/assets/javascripts/concerto_template_scheduling/application.js +13 -0
- data/app/assets/javascripts/concerto_template_scheduling/schedules.js +25 -0
- data/app/assets/stylesheets/concerto_template_scheduling/application.css +13 -0
- data/app/assets/stylesheets/concerto_template_scheduling/schedules.css +4 -0
- data/app/assets/stylesheets/scaffold.css +56 -0
- data/app/controllers/concerto_template_scheduling/application_controller.rb +4 -0
- data/app/controllers/concerto_template_scheduling/schedules_controller.rb +106 -0
- data/app/helpers/concerto_template_scheduling/application_helper.rb +4 -0
- data/app/helpers/concerto_template_scheduling/schedules_helper.rb +4 -0
- data/app/models/concerto_template_scheduling/schedule.rb +181 -0
- data/app/views/concerto_template_scheduling/schedules/_form.html.erb +118 -0
- data/app/views/concerto_template_scheduling/schedules/edit.html.erb +8 -0
- data/app/views/concerto_template_scheduling/schedules/index.html.erb +82 -0
- data/app/views/concerto_template_scheduling/schedules/new.html.erb +8 -0
- data/app/views/concerto_template_scheduling/schedules/show.html.erb +54 -0
- data/app/views/concerto_template_scheduling/screens/_screen_link.html.erb +66 -0
- data/app/views/concerto_template_scheduling/templates/_in_use_by.html.erb +11 -0
- data/config/locales/en.yml +62 -0
- data/config/routes.rb +5 -0
- data/db/migrate/20140118205731_create_concerto_template_scheduling_schedules.rb +13 -0
- data/lib/concerto_template_scheduling.rb +4 -0
- data/lib/concerto_template_scheduling/engine.rb +69 -0
- data/lib/concerto_template_scheduling/version.rb +3 -0
- data/lib/tasks/concerto_template_scheduling_tasks.rake +4 -0
- data/test/concerto_template_scheduling_test.rb +7 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +29 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +36 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/fixtures/concerto_template_scheduling/schedules.yml +11 -0
- data/test/functional/concerto_template_scheduling/schedules_controller_test.rb +51 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +15 -0
- data/test/unit/concerto_template_scheduling/schedule_test.rb +9 -0
- data/test/unit/helpers/concerto_template_scheduling/schedules_helper_test.rb +6 -0
- metadata +202 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 19a1b3329508cae93b9159a4f5a799a5cc657305
|
4
|
+
data.tar.gz: dfcd729f0c7eef50ef11cbbba06252a8e09ce1fa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bc389fe4c6c5dd23fe2c840bfd09d8f81865d39ec2547db3ac2f575f398aeecdd8f47011f5ebfe7aaeafa53190c5fc8dac55fd1f8e023927a5f55bfe4b4bf851
|
7
|
+
data.tar.gz: 8cc002b04ee118f3f66b2902ddcfdfa96e6cc0ef21c0d8910b0d3f4313fe270c4a12b43fc2b10f1c9f85a00e8835272279e84605a4a91792dae12a95f2ff57f6
|
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2014 Concerto Authors
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Concerto Template Scheduling
|
2
|
+
|
3
|
+
A Rails Engine for scheduling templates for your screens in Concerto.
|
4
|
+
|
5
|
+
Templates can be scheduled for a specific time frame for specific days. A template will be made active when this
|
6
|
+
scheduling criteria is met. A template can also be made active when content exists on a specified feed-- such as when
|
7
|
+
you want travel advisories or weather alerts to show at the bottom of your screen while still having your other content
|
8
|
+
shown.
|
9
|
+
|
10
|
+
To use this engine, add the following to the Concerto Gemfile:
|
11
|
+
```
|
12
|
+
gem 'concerto_template_scheduling'
|
13
|
+
```
|
14
|
+
|
15
|
+
To create the proper migrations, run:
|
16
|
+
```
|
17
|
+
rails generate concerto_template_scheduling
|
18
|
+
```
|
19
|
+
|
20
|
+
## Security
|
21
|
+
If a user can update a screen, they have the ability to manage the scheduled templates for that screen.
|
22
|
+
|
23
|
+
## Requirements
|
24
|
+
`start_time` and `end_time` setters (in the model) don't work well with ruby 1.8.7.
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'ConcertoTemplateScheduling'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'lib'
|
28
|
+
t.libs << 'test'
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
30
|
+
t.verbose = false
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
task default: :test
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,25 @@
|
|
1
|
+
// Place all the behaviors and hooks related to the matching controller here.
|
2
|
+
// All this logic will automatically be available in application.js.
|
3
|
+
|
4
|
+
function attachConcertoTemplateSchedulingHandlers() {
|
5
|
+
$('select#schedule_config_display_when').on('change', toggleCtsFormFields);
|
6
|
+
|
7
|
+
function toggleCtsFormFields() {
|
8
|
+
var dw = $('select#schedule_config_display_when').val();
|
9
|
+
if (dw == 3) { // 'content exists'
|
10
|
+
$('#feed_selection').show();
|
11
|
+
$('#scheduling_criteria').hide();
|
12
|
+
} else if (dw == 2) { // 'by criteria'
|
13
|
+
$('#feed_selection').hide();
|
14
|
+
$('#scheduling_criteria').show();
|
15
|
+
} else {
|
16
|
+
$('#feed_selection').hide();
|
17
|
+
$('#scheduling_criteria').hide();
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
toggleCtsFormFields();
|
22
|
+
}
|
23
|
+
|
24
|
+
$(document).ready(attachConcertoTemplateSchedulingHandlers);
|
25
|
+
$(document).on('page:change', attachConcertoTemplateSchedulingHandlers);
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|
@@ -0,0 +1,56 @@
|
|
1
|
+
body { background-color: #fff; color: #333; }
|
2
|
+
|
3
|
+
body, p, ol, ul, td {
|
4
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
5
|
+
font-size: 13px;
|
6
|
+
line-height: 18px;
|
7
|
+
}
|
8
|
+
|
9
|
+
pre {
|
10
|
+
background-color: #eee;
|
11
|
+
padding: 10px;
|
12
|
+
font-size: 11px;
|
13
|
+
}
|
14
|
+
|
15
|
+
a { color: #000; }
|
16
|
+
a:visited { color: #666; }
|
17
|
+
a:hover { color: #fff; background-color:#000; }
|
18
|
+
|
19
|
+
div.field, div.actions {
|
20
|
+
margin-bottom: 10px;
|
21
|
+
}
|
22
|
+
|
23
|
+
#notice {
|
24
|
+
color: green;
|
25
|
+
}
|
26
|
+
|
27
|
+
.field_with_errors {
|
28
|
+
padding: 2px;
|
29
|
+
background-color: red;
|
30
|
+
display: table;
|
31
|
+
}
|
32
|
+
|
33
|
+
#error_explanation {
|
34
|
+
width: 450px;
|
35
|
+
border: 2px solid red;
|
36
|
+
padding: 7px;
|
37
|
+
padding-bottom: 0;
|
38
|
+
margin-bottom: 20px;
|
39
|
+
background-color: #f0f0f0;
|
40
|
+
}
|
41
|
+
|
42
|
+
#error_explanation h2 {
|
43
|
+
text-align: left;
|
44
|
+
font-weight: bold;
|
45
|
+
padding: 5px 5px 5px 15px;
|
46
|
+
font-size: 12px;
|
47
|
+
margin: -7px;
|
48
|
+
margin-bottom: 0px;
|
49
|
+
background-color: #c00;
|
50
|
+
color: #fff;
|
51
|
+
}
|
52
|
+
|
53
|
+
#error_explanation ul li {
|
54
|
+
font-size: 12px;
|
55
|
+
list-style: square;
|
56
|
+
}
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require_dependency "concerto_template_scheduling/application_controller"
|
2
|
+
|
3
|
+
module ConcertoTemplateScheduling
|
4
|
+
class SchedulesController < ApplicationController
|
5
|
+
# since scheduled templates are basically an extended feature of a screen
|
6
|
+
# if the user can update the screen then they can crud scheduled templates
|
7
|
+
|
8
|
+
# GET /schedules
|
9
|
+
# GET /schedules.json
|
10
|
+
def index
|
11
|
+
@schedules = Schedule.all
|
12
|
+
# ignore the schedules that belong to screens we cant read
|
13
|
+
# or schedules where the template has been deleted
|
14
|
+
@schedules.reject! { |s| !can?(:read, s.screen) || s.template.nil? }
|
15
|
+
|
16
|
+
respond_to do |format|
|
17
|
+
format.html # index.html.erb
|
18
|
+
format.json { render json: @schedules }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# GET /schedules/1
|
23
|
+
# GET /schedules/1.json
|
24
|
+
def show
|
25
|
+
@schedule = Schedule.find(params[:id])
|
26
|
+
auth! :action => :read, :object => @schedule.screen
|
27
|
+
|
28
|
+
respond_to do |format|
|
29
|
+
format.html # show.html.erb
|
30
|
+
format.json { render json: @schedule }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# GET /schedules/new
|
35
|
+
# GET /schedules/new.json
|
36
|
+
def new
|
37
|
+
@schedule = Schedule.new
|
38
|
+
if !params[:screen_id].nil?
|
39
|
+
# TODO: Error handling
|
40
|
+
@schedule.screen = Screen.find(params[:screen_id])
|
41
|
+
end
|
42
|
+
auth! :action => :update, :object => @schedule.screen
|
43
|
+
|
44
|
+
respond_to do |format|
|
45
|
+
format.html # new.html.erb
|
46
|
+
format.json { render json: @schedule }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# GET /schedules/1/edit
|
51
|
+
def edit
|
52
|
+
@schedule = Schedule.find(params[:id])
|
53
|
+
auth! :action => :update, :object => @schedule.screen
|
54
|
+
end
|
55
|
+
|
56
|
+
# POST /schedules
|
57
|
+
# POST /schedules.json
|
58
|
+
def create
|
59
|
+
@schedule = Schedule.new(schedule_params)
|
60
|
+
auth! :action => :update, :object => @schedule.screen
|
61
|
+
respond_to do |format|
|
62
|
+
if @schedule.save
|
63
|
+
format.html { redirect_to @schedule, notice: 'Schedule was successfully created.' }
|
64
|
+
format.json { render json: @schedule, status: :created, location: @schedule }
|
65
|
+
else
|
66
|
+
format.html { render action: "new" }
|
67
|
+
format.json { render json: @schedule.errors, status: :unprocessable_entity }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# PUT /schedules/1
|
73
|
+
# PUT /schedules/1.json
|
74
|
+
def update
|
75
|
+
@schedule = Schedule.find(params[:id])
|
76
|
+
auth! :action => :update, :object => @schedule.screen
|
77
|
+
|
78
|
+
respond_to do |format|
|
79
|
+
if @schedule.update_attributes(schedule_params)
|
80
|
+
format.html { redirect_to @schedule, notice: 'Schedule was successfully updated.' }
|
81
|
+
format.json { head :no_content }
|
82
|
+
else
|
83
|
+
format.html { render action: "edit" }
|
84
|
+
format.json { render json: @schedule.errors, status: :unprocessable_entity }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# DELETE /schedules/1
|
90
|
+
# DELETE /schedules/1.json
|
91
|
+
def destroy
|
92
|
+
@schedule = Schedule.find(params[:id])
|
93
|
+
auth! :action => :update, :object => @schedule.screen
|
94
|
+
@schedule.destroy
|
95
|
+
|
96
|
+
respond_to do |format|
|
97
|
+
format.html { redirect_to schedules_url }
|
98
|
+
format.json { head :no_content }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def schedule_params
|
103
|
+
params.require(:schedule).permit(*ConcertoTemplateScheduling::Schedule.form_attributes)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
module ConcertoTemplateScheduling
|
2
|
+
class Schedule < ActiveRecord::Base
|
3
|
+
include ActiveModel::ForbiddenAttributesProtection
|
4
|
+
|
5
|
+
DISPLAY_NEVER=0
|
6
|
+
DISPLAY_ALWAYS=1
|
7
|
+
DISPLAY_AS_SCHEDULED=2
|
8
|
+
DISPLAY_CONTENT_EXISTS=3
|
9
|
+
|
10
|
+
DISPLAY_WHEN = {
|
11
|
+
I18n.t('concerto_template_scheduling.never') => DISPLAY_NEVER,
|
12
|
+
I18n.t('concerto_template_scheduling.always') => DISPLAY_ALWAYS,
|
13
|
+
I18n.t('concerto_template_scheduling.as_scheduled') => DISPLAY_AS_SCHEDULED,
|
14
|
+
I18n.t('concerto_template_scheduling.content_exists') => DISPLAY_CONTENT_EXISTS
|
15
|
+
}
|
16
|
+
|
17
|
+
belongs_to :screen
|
18
|
+
belongs_to :template
|
19
|
+
|
20
|
+
attr_accessor :config
|
21
|
+
|
22
|
+
after_initialize :create_config
|
23
|
+
after_find :load_config
|
24
|
+
before_validation :save_config
|
25
|
+
|
26
|
+
validates_associated :screen
|
27
|
+
validates_presence_of :screen, :message => I18n.t('concerto_template_scheduling.must_be_selected')
|
28
|
+
# do not require uniqueness because the same template may be scheduled
|
29
|
+
# for different time frames with different occurrence criteria
|
30
|
+
# validates_uniqueness_of :template_id, :scope => :screen_id
|
31
|
+
|
32
|
+
validates_associated :template
|
33
|
+
validates_presence_of :template, :message => I18n.t('concerto_template_scheduling.must_be_selected')
|
34
|
+
|
35
|
+
validate :from_time_must_precede_to_time
|
36
|
+
validate :schedule_must_be_defined
|
37
|
+
|
38
|
+
def from_time_must_precede_to_time
|
39
|
+
if Time.zone.parse(self.config['from_time']) > Time.zone.parse(self.config['to_time'])
|
40
|
+
errors.add(:base, I18n.t('concerto_template_scheduling.from_time_must_precede_to_time'))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def schedule_must_be_defined
|
45
|
+
if self.config['display_when'].to_i == DISPLAY_AS_SCHEDULED
|
46
|
+
if self.config['scheduling_criteria'].empty?
|
47
|
+
errors.add(:base, I18n.t('concerto_template_scheduling.schedule_must_be_defined'))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.active
|
53
|
+
where("start_time < :now AND end_time > :now", {:now => Clock.time})
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.form_attributes
|
57
|
+
attributes = [:screen_id, :template_id,
|
58
|
+
{:start_time => [:time, :date]}, {:end_time => [:time, :date]},
|
59
|
+
{:config => [:display_when, :from_time, :to_time, :feed_id, :scheduling_criteria]}]
|
60
|
+
end
|
61
|
+
|
62
|
+
# Specify the default configuration hash.
|
63
|
+
# This will be used if a configuration doesn't exist.
|
64
|
+
#
|
65
|
+
# @return [Hash{String => String, Number}] configuration hash.
|
66
|
+
def default_config
|
67
|
+
{
|
68
|
+
'display_when' => DISPLAY_ALWAYS,
|
69
|
+
'from_time' => '12:00am',
|
70
|
+
'to_time' => '11:59pm'
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
# Create a new configuration hash if one does not already exist.
|
75
|
+
# Called during `after_initialize`, where a config may or may not exist.
|
76
|
+
def create_config
|
77
|
+
self.start_time ||= Time.zone.parse("12:00am", Clock.time + ConcertoConfig[:start_date_offset].to_i.days)
|
78
|
+
self.end_time ||= Time.zone.parse("11:59pm", Clock.time + ConcertoConfig[:start_date_offset].to_i.days + ConcertoConfig[:default_content_run_time].to_i.days)
|
79
|
+
|
80
|
+
self.config = {} if !self.config
|
81
|
+
self.config = default_config().merge(self.config)
|
82
|
+
self.config
|
83
|
+
end
|
84
|
+
|
85
|
+
# Load a configuration hash.
|
86
|
+
# Converts the JSON data stored for the schedule into the configuration.
|
87
|
+
# Called during `after_find`.
|
88
|
+
def load_config
|
89
|
+
self.config = JSON.load(self.data)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Prepare the configuration to be saved.
|
93
|
+
# Compress the config hash back into JSON to be stored in the database.
|
94
|
+
# Called during `before_validation`.
|
95
|
+
def save_config
|
96
|
+
self.config['scheduling_criteria'] = '' if self.config['scheduling_criteria'] == 'null'
|
97
|
+
self.data = JSON.dump(self.config)
|
98
|
+
end
|
99
|
+
|
100
|
+
# TODO: make sure these formats are locale-ized!
|
101
|
+
|
102
|
+
# Setter for the start time. If a hash is passed, convert that into a DateTime object and then a string.
|
103
|
+
# Otherwise, just set it like normal. This is a bit confusing due to the differences in how Ruby handles
|
104
|
+
# times between 1.9.x and 1.8.x.
|
105
|
+
def start_time=(_start_time)
|
106
|
+
if _start_time.kind_of?(Hash)
|
107
|
+
#write_attribute(:start_time, Time.parse("#{_start_time[:date]} #{_start_time[:time]}").to_s(:db))
|
108
|
+
# convert to time, strip off the timezone offset so it reflects local time
|
109
|
+
t = DateTime.strptime("#{_start_time[:date]} #{_start_time[:time]}", "%m/%d/%Y %l:%M %p")
|
110
|
+
write_attribute(:start_time, Time.zone.parse(t.utc.iso8601.slice(0, 19)).to_s(:db))
|
111
|
+
else
|
112
|
+
write_attribute(:start_time, _start_time)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# See start_time=.
|
117
|
+
def end_time=(_end_time)
|
118
|
+
if _end_time.kind_of?(Hash)
|
119
|
+
# convert to time, strip off the timezone offset so it reflects local time
|
120
|
+
t = DateTime.strptime("#{_end_time[:date]} #{_end_time[:time]}", "%m/%d/%Y %l:%M %p")
|
121
|
+
write_attribute(:end_time, Time.zone.parse(t.utc.iso8601.slice(0, 19)).to_s(:db))
|
122
|
+
else
|
123
|
+
write_attribute(:end_time, _end_time)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def schedule_in_words
|
128
|
+
if !self.config['scheduling_criteria'].empty?
|
129
|
+
s = IceCube::Schedule.new(self.start_time)
|
130
|
+
s.add_recurrence_rule(RecurringSelect.dirty_hash_to_rule(self.config['scheduling_criteria']))
|
131
|
+
s.to_s
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def is_effective?
|
136
|
+
effective = false
|
137
|
+
|
138
|
+
# if it is during the valid/active time frame and the template still exists
|
139
|
+
if Clock.time >= self.start_time && Clock.time <= self.end_time && !self.template.nil?
|
140
|
+
# and it is within the viewing window for the day
|
141
|
+
if Clock.time >= Time.parse(self.config['from_time']) && Clock.time <= Time.parse(self.config['to_time'])
|
142
|
+
# and it is either marked as always shown
|
143
|
+
if self.config['display_when'].to_i == DISPLAY_ALWAYS
|
144
|
+
effective = true
|
145
|
+
elsif self.config['display_when'].to_i == DISPLAY_CONTENT_EXISTS
|
146
|
+
# or if we detect actual content on the specified feed
|
147
|
+
if !self.feed.nil? && !self.feed.approved_contents.active.where('kind_id != 4').empty?
|
148
|
+
effective = true
|
149
|
+
end
|
150
|
+
elsif self.config['display_when'].to_i == DISPLAY_AS_SCHEDULED
|
151
|
+
if !self.config['scheduling_criteria'].empty?
|
152
|
+
s = IceCube::Schedule.new(self.start_time)
|
153
|
+
s.add_recurrence_rule(RecurringSelect.dirty_hash_to_rule(self.config['scheduling_criteria']))
|
154
|
+
effective = s.occurs_on? Clock.time
|
155
|
+
else
|
156
|
+
# no schedule was set
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
effective
|
163
|
+
end
|
164
|
+
|
165
|
+
def feed
|
166
|
+
if self.config.include?('feed_id')
|
167
|
+
f = Feed.find(self.config['feed_id'].to_i)
|
168
|
+
end
|
169
|
+
f
|
170
|
+
end
|
171
|
+
|
172
|
+
def selectable_feeds
|
173
|
+
if !self.screen.nil?
|
174
|
+
feeds = Feed.all
|
175
|
+
ability = Ability.new(self.screen)
|
176
|
+
feeds.reject { |feed| !ability.can?(:read, feed) }
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
end
|