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
         
     |