concerto_hardware 0.2 → 0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 78926444b14981b5a897bcbd8662f7d1abb5d2b6
4
- data.tar.gz: 7e521966dae2d75ab103e62869eac6019100de01
3
+ metadata.gz: 7755452c779d4727103fc30b2a4240fab346bcf0
4
+ data.tar.gz: b4ac85892d72694abe88eb8203230083e479a631
5
5
  SHA512:
6
- metadata.gz: f13bb763b161fa1cb5c10e662326d1a2261bc7e8369276d642ee9302850e2edb76dbd3ac908848a1b955851a45d37a5bd62f2d53b66da2e7a23330778f51414d
7
- data.tar.gz: 115b314f996a2b566da9e0d91605abc70e93f9882f37956632a71a4681100bcffbbf1de3f642bd7a9b85fdea18aa77ca04bef493d94729579c307065124f5c16
6
+ metadata.gz: 527f89252a3e7aaf88468aa0e606d2cacc40c0690300625277d38b675630f12776d3bdf83941d9df5689976643477e2114d0f2738830a96a717c6b9e2d0bf80f
7
+ data.tar.gz: c91e1657fb61bcafd689e9eeee934454dce3b028b557672b1517b871711c2208085e187358ece759c0a543bc3d7dff55ac670169dcf007e7fdc3c0201691eb3c
@@ -1,15 +1,18 @@
1
- // This is a manifest file that'll be compiled into application.js, which will include all the files
2
- // listed below.
1
+ // This is a manifest file that will compile javascripts used by this plugn's
2
+ // views. This plugin is configured to use the main application's layouts, so
3
+ // it adds to what is available there, and its assets are not meant for
4
+ // standalone use.
3
5
  //
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
+ // The plugin is added to the application's layout via a hook in enine.rb.
6
7
  //
7
- // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
- // the compiled file.
8
+ // We make the assumption that jquery and jquery_ujs have been included
9
+ // by Concerto's application.js before this file is loaded, so we can
10
+ // skip those includes.
9
11
  //
10
- // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
- // GO AFTER THE REQUIRES BELOW.
12
+ // It's not advisable to add code directly here, but if you do, it'll appear
13
+ // at the bottom of the compiled file.
14
+ //
15
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED,
16
+ // ANY BLANK LINE SHOULD GO AFTER THE REQUIRES BELOW.
12
17
  //
13
- //= require jquery
14
- //= require jquery_ujs
15
18
  //= require_tree .
@@ -1,2 +1,25 @@
1
1
  // Place all the behaviors and hooks related to the matching controller here.
2
- // All this logic will automatically be available in application.js.
2
+ // All this logic will automatically be available in plugin.js
3
+
4
+ // Namespace the plugin for neatness
5
+ var ConcertoHardware = {
6
+ updateWkndOnOff: function() {
7
+ if ($('#player_wknd_disable').is(':checked')) {
8
+ $('#wknd_on_time_div').hide();
9
+ $('#wknd_off_time_div').hide();
10
+ } else {
11
+ $('#wknd_on_time_div').show();
12
+ $('#wknd_off_time_div').show();
13
+ }
14
+ },
15
+
16
+ initPlayers: function() {
17
+ ConcertoHardware.updateWkndOnOff();
18
+ $('#player_wknd_disable').change(function() {
19
+ ConcertoHardware.updateWkndOnOff();
20
+ });
21
+ }
22
+ };
23
+
24
+ $(document).ready(ConcertoHardware.initPlayers);
25
+ $(document).on('page:change', ConcertoHardware.initPlayers);
@@ -7,10 +7,11 @@ module ConcertoHardware
7
7
  # Note that links back to the main application will need to directly
8
8
  # reference the main_app router.
9
9
  class ApplicationController < ::ApplicationController
10
+ unloadable # Marks this class for reloading in development mode
10
11
  def current_ability
11
12
  # Use the Ability class defined in this engine's namespace.
12
13
  # It is designed to also include the rules from the main app.
13
- @current_ability ||= Ability.new(current_accessor)
14
+ @current_ability ||= ConcertoHardware::Ability.new(current_accessor)
14
15
  end
15
16
  end
16
17
  end
@@ -1,8 +1,5 @@
1
- require_dependency "concerto_hardware/application_controller"
2
-
3
1
  module ConcertoHardware
4
- class PlayersController < ApplicationController
5
- unloadable #marks this class for reloading in between requests
2
+ class PlayersController < ConcertoHardware::ApplicationController
6
3
  #include routes.named_routes.helpers
7
4
  before_filter :screen_api
8
5
 
@@ -50,45 +47,12 @@ class PlayersController < ApplicationController
50
47
  end
51
48
  end
52
49
 
53
- # GET /players/new
54
- # GET /players/new.json
55
- def new
56
- @player = Player.new
57
- if !params[:screen_id].nil?
58
- # TODO: Error handling
59
- @player.screen = Screen.find(params[:screen_id])
60
- end
61
- auth!
62
-
63
- respond_to do |format|
64
- format.html # new.html.erb
65
- format.json { render :json => @player }
66
- end
67
- end
68
-
69
50
  # GET /players/1/edit
70
51
  def edit
71
52
  @player = Player.find(params[:id])
72
53
  auth!
73
54
  end
74
55
 
75
- # POST /players
76
- # POST /players.json
77
- def create
78
- @player = Player.new(player_params)
79
- auth!
80
-
81
- respond_to do |format|
82
- if @player.save
83
- format.html { redirect_to [hardware, @player], :notice => 'Player was successfully created.' }
84
- format.json { render :json => @player, :status => :created, :location => @player }
85
- else
86
- format.html { render :action => "new" }
87
- format.json { render :json => @player.errors, :status => :unprocessable_entity }
88
- end
89
- end
90
- end
91
-
92
56
  # PUT /players/1
93
57
  # PUT /players/1.json
94
58
  def update
@@ -124,7 +88,7 @@ class PlayersController < ApplicationController
124
88
  # Deal with strong parameter restrictions.
125
89
  def player_params
126
90
  params.require(:player).permit(:wkday_on_time, :wkday_off_time,
127
- :wknd_on_time, :wkday_off_time, :wknd_disable, :force_off)
91
+ :wknd_on_time, :wknd_off_time, :wknd_disable, :force_off)
128
92
  end
129
93
  end
130
94
 
@@ -24,10 +24,28 @@ module ConcertoHardware
24
24
  validates_presence_of :screen, :message => 'must exist'
25
25
  validates_uniqueness_of :screen_id
26
26
 
27
+ # Time virtual attributes return nil if an invalid attribute
28
+ # was given.
29
+ validates :wkday_on_time, :wkday_off_time, :presence => {
30
+ :message => :must_be_valid_time
31
+ }
32
+ validates :wknd_on_time, :wknd_off_time, :presence => {
33
+ :unless => "wknd_disable?",
34
+ :message => :must_be_valid_time
35
+ }
36
+ validate :on_must_come_before_off
37
+
27
38
  after_initialize :default_values
28
39
  after_find :retrieve_screen_on_off
29
40
  before_save :process_screen_on_off
30
41
 
42
+ # Evaluates truthiness of the virtual attribute.
43
+ def wknd_disable?
44
+ return true if self.wknd_disable == "1"
45
+ return true if self.wknd_disable == true
46
+ return false
47
+ end
48
+
31
49
  def default_values
32
50
  self.screen_on_off ||= [
33
51
  {
@@ -51,10 +69,15 @@ module ConcertoHardware
51
69
  # https://github.com/concerto/concerto-hardware/
52
70
  # wiki/Player-API#screen-onoff-times
53
71
  # TODO: Formatting for datetimes
54
- # TODO: Validation
55
72
  # TODO: TIMEZONES
56
73
  def process_screen_on_off
57
74
  ruleset = []
75
+ if wknd_disable?
76
+ # Special case: we can ignore invlaid wknd times if we're off
77
+ # on the weekend (avoids a rough edge on form submission).
78
+ self.wknd_on_time = "09:00" if wknd_on_time.nil?
79
+ self.wknd_off_time = "23:00" if wknd_off_time.nil?
80
+ end
58
81
  unless self.wkday_on_time.nil? or self.wkday_off_time.nil?
59
82
  ruleset << {
60
83
  :action => "on",
@@ -65,7 +88,7 @@ module ConcertoHardware
65
88
  end
66
89
  unless self.wknd_on_time.nil? or self.wknd_off_time.nil?
67
90
  ruleset << {
68
- :action => self.wknd_disable=="1" ? "off" : "on",
91
+ :action => self.wknd_disable? ? "off" : "on",
69
92
  :wkday => "06", # Sun, Sat
70
93
  :time_after => fmt_time(wknd_on_time), # "07:00"
71
94
  :time_before => fmt_time(wknd_off_time), # "23:00"
@@ -138,7 +161,7 @@ module ConcertoHardware
138
161
  else
139
162
  rules << "Weekdays: on at "+fmt_time(wkday_on_time, "%l:%M%P")+", "+
140
163
  "off at "+fmt_time(wkday_off_time, "%l:%M%P")+"."
141
- if wknd_disable
164
+ if wknd_disable?
142
165
  rules << "Weekends: off."
143
166
  else
144
167
  rules << "Weekends: on at "+fmt_time(wknd_on_time, "%l:%M%P")+", "+
@@ -171,5 +194,22 @@ module ConcertoHardware
171
194
  json
172
195
  end
173
196
 
197
+ private
198
+
199
+ # Time order validation method
200
+ def on_must_come_before_off
201
+ unless wkday_off_time.nil? or wkday_on_time.nil?
202
+ if wkday_off_time < wkday_on_time
203
+ errors.add :wkday_off_time, :must_come_after,
204
+ :before => self.class.human_attribute_name(:wkday_on_time)
205
+ end
206
+ end
207
+ unless wknd_off_time.nil? or wknd_on_time.nil? or wknd_disable?
208
+ if wknd_off_time < wknd_on_time
209
+ errors.add :wknd_off_time, :must_come_after,
210
+ :before => self.class.human_attribute_name(:wknd_on_time)
211
+ end
212
+ end
213
+ end
174
214
  end # class Player
175
215
  end # module ConcertoHardware
@@ -44,14 +44,14 @@
44
44
  </ul>
45
45
  </div>
46
46
  </div>
47
- <div class="clearfix">
47
+ <div class="clearfix" id="wknd_on_time_div">
48
48
  <%= f.label :wknd_on_time %>
49
49
  <div class="input-prepend">
50
50
  <span class="add-on"><%= t(:at) %></span>
51
51
  <%= f.text_field(:wknd_on_time, :maxlength => 20, :class => "timefield input-small", :value => @player.fmt_time(@player.wknd_on_time, "%l:%M%P") || ConcertoConfig[:content_default_start_time]) %>
52
52
  </div>
53
53
  </div>
54
- <div class="clearfix">
54
+ <div class="clearfix" id="wknd_off_time_div">
55
55
  <%= f.label :wknd_off_time %>
56
56
  <div class="input-prepend">
57
57
  <span class="add-on"><%= t(:at) %></span>
@@ -62,11 +62,10 @@
62
62
  <div class="clearfix">
63
63
  <div class="input checkbox">
64
64
  <ul class="inputs-list">
65
- <li><%= f.check_box :force_off %> <%= f.label :force_off %> (temporarily turns off the screen until midnight tonight)</li>
65
+ <li><%= f.check_box :force_off %> <%= f.label :force_off %> (<%= t('.force_off_msg') %>)</li>
66
66
  </ul>
67
67
  </div>
68
68
  </div>
69
- <p><em>All time fields should be entered in 24 hour format (HH:mm), for example 23:30 for 11:30 PM.</em></p>
70
69
  </fieldset>
71
70
 
72
71
  <div class="submit_bar actions">
@@ -7,14 +7,14 @@
7
7
  <p id="notice"><%= notice %></p>
8
8
 
9
9
  <p>
10
- <b>Ip address:</b>
10
+ <b><%= ConcertoHardware::Player.human_attribute_name(:ip_address) %>:</b>
11
11
  <%= @player.ip_address %>
12
12
  </p>
13
13
 
14
14
  <p>
15
- <b>Screen:</b>
15
+ <b><%= ConcertoHardware::Player.human_attribute_name(:screen) %>:</b>
16
16
  <% if @player.screen.nil? %>
17
- Not found
17
+ <%= t('.no_screen_found') %>
18
18
  <% else %>
19
19
  <% if can? :read, @player.screen %>
20
20
  <%= link_to @player.screen.name, [main_app, @player.screen] %>
@@ -25,12 +25,12 @@
25
25
  </p>
26
26
 
27
27
  <p>
28
- <b>Activated:</b>
28
+ <b><%= ConcertoHardware::Player.human_attribute_name(:activated) %>:</b>
29
29
  <%= @player.activated %>
30
30
  </p>
31
31
 
32
32
  <p>
33
- <b>Screen on/off times:</b>
33
+ <b><%= ConcertoHardware::Player.human_attribute_name(:screen_on_off_times) %>:</b>
34
34
  <ul>
35
35
  <% @player.describe_screen_on_off.each do |rule| %>
36
36
  <li><%=rule%></li>
@@ -1,12 +1,5 @@
1
1
  <section class="viewblock">
2
2
  <header class="viewblock-header">
3
- <div class="viewblock-header_right">
4
- <div class="button-padding">
5
- <% if can? :create, ConcertoHardware::Player %>
6
- <%= link_to t(:new_model, :model => ConcertoHardware::Player.model_name.human), new_player_path, :class => "btn" %>
7
- <% end %>
8
- </div>
9
- </div>
10
3
  <h1 class="default-padding">
11
4
  <%= t(:all_model, :model => ConcertoHardware::Player.model_name.human.pluralize) %>
12
5
  </h1>
@@ -46,4 +39,5 @@
46
39
  <div class="default-padding">
47
40
  <%# for demo purposes: %>
48
41
  Note: the poll interval is currently set to <%=ConcertoConfig[:poll_interval]%> seconds.
49
- </div>
42
+ </div>
43
+
@@ -6,7 +6,7 @@
6
6
  <div class="viewblock-header_right">
7
7
  <div class="button-padding">
8
8
  <% if (!@player.nil?) && (can? :update, @player) %>
9
- <%= link_to 'Edit Player', hardware.edit_player_path(@player), :class => "btn" %>
9
+ <%= link_to t('.player_settings'), hardware.edit_player_path(@player), :class => "btn" %>
10
10
  <% end %>
11
11
  </div>
12
12
  </div>
@@ -24,11 +24,16 @@
24
24
  </div>
25
25
  <% else %>
26
26
  <h3><%= @screen.name + " Player" %></h3>
27
- <p><b><%= @player.activated ? t('.activated') : t('.not_activated') %></b></p>
27
+ <p><b><%= @player.activated ? t('.is_activated') : t('.not_activated') %></b></p>
28
28
  <br />
29
29
  <% if can? :read, @player %>
30
- <% if current_user %><p><b>IP Address:</b> <%= @player.ip_address %></p><% end %>
31
- <p><b>Screen On/Off Times:</b></p>
30
+ <% if current_user %>
31
+ <p>
32
+ <b><%= ConcertoHardware::Player.human_attribute_name(:ip_address)%>:</b>
33
+ <%= @player.ip_address %>
34
+ </p>
35
+ <% end %>
36
+ <p><b><%= ConcertoHardware::Player.human_attribute_name(:screen_on_off_times)%>:</b></p>
32
37
  <ul>
33
38
  <% @player.describe_screen_on_off.each do |rule| %>
34
39
  <li><%= rule %></li>
@@ -6,11 +6,17 @@ en:
6
6
  concerto_hardware/player:
7
7
  activated: 'Active'
8
8
  ip_address: 'IP Address'
9
- wkday_on_time: 'Weekday turn On time'
10
- wkday_off_time: 'Weekday turn Off time'
9
+ wkday_on_time: 'Weekday turn on time'
10
+ wkday_off_time: 'Weekday turn off time'
11
11
  wknd_disable: 'Disable on weekends'
12
- wknd_on_time: 'Weekend turn On time'
13
- wknd_off_time: 'Weekend turn Off time'
12
+ wknd_on_time: 'Weekend turn on time'
13
+ wknd_off_time: 'Weekend turn off time'
14
+ screen_on_off_times: "Screen On/Off Times"
15
+ errors:
16
+ models:
17
+ concerto_hardware/player:
18
+ must_be_valid_time: 'must be a valid time of day'
19
+ must_come_after: 'must come after %{before}'
14
20
 
15
21
  concerto_hardware:
16
22
  players:
@@ -18,6 +24,13 @@ en:
18
24
  header: 'New %{screen} Player'
19
25
  edit:
20
26
  header: 'Edit %{screen} Player'
27
+ form:
28
+ provide_details: "Provide Details"
29
+ force_off_msg: "temporarily turns off the screen until midnight tonight"
30
+ show_body:
31
+ no_screen_found: "No Screen Found"
32
+ is_activated: "Activated"
33
+ not_activated: "Not Activated"
21
34
 
22
35
  screens:
23
36
  screen_link:
@@ -25,5 +38,6 @@ en:
25
38
  no_player_header: "No Player"
26
39
  no_player_msg: "A Concerto Player has not yet been connected to this screen."
27
40
  add_player_msg: "Specify a Player manually."
28
- activated: "Activated"
29
- not_activated: "Not Activated"
41
+ player_settings: "Player Settings"
42
+ is_activated: "Activated"
43
+ not_activated: "Not Activated"
data/config/routes.rb CHANGED
@@ -10,7 +10,7 @@ ConcertoHardware::Engine.routes.draw do
10
10
 
11
11
  # Since we have an isolated namespace, routes are automaticaly scoped
12
12
  # to the ConcertoHardware module.
13
- resources :players do
13
+ resources :players, :except => [:new, :create] do
14
14
  collection do
15
15
  # Look up a player based on the screen ID.
16
16
  get 'by_screen/:screen_id' => ConcertoHardware::PlayersController.action(:show)
@@ -32,6 +32,10 @@ module ConcertoHardware
32
32
  # The following hooks allow integration into the main Concerto app
33
33
  # at the controller and view levels.
34
34
 
35
+ add_header_tags do
36
+ javascript_include_tag "concerto_hardware/application"
37
+ end
38
+
35
39
  add_controller_hook "ScreensController", :show, :before do
36
40
  @player = Player.find_by_screen_id(@screen.id)
37
41
  end
@@ -31,18 +31,22 @@ module ConcertoHardware
31
31
  self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
32
32
  def #{sym}
33
33
  if @#{sym}_timeobj.is_a? Time
34
- @#{sym}_timeobj.to_s
34
+ @#{sym}_timeobj
35
35
  else
36
36
  nil
37
37
  end
38
38
  end
39
39
  def #{sym}=(val)
40
+ @#{sym}_timeobj = nil
40
41
  if val.is_a? Time
41
42
  @#{sym}_timeobj = val
42
43
  elsif val.is_a? String
43
- @#{sym}_timeobj = Time.parse(val)
44
- else
45
- raise ArgumentError.new("Only Strings or Times allowed")
44
+ begin
45
+ @#{sym}_timeobj = Time.parse(val)
46
+ rescue ArgumentError => e
47
+ # Example: empty string or not a time
48
+ # Value gets nil, which validations will flag.
49
+ end
46
50
  end
47
51
  end
48
52
  RUBY
@@ -1,3 +1,3 @@
1
1
  module ConcertoHardware
2
- VERSION = "0.2"
2
+ VERSION = "0.3"
3
3
  end
@@ -1,4 +1,5 @@
1
1
  require "concerto_hardware/engine"
2
+ require "concerto_hardware/time_accessible"
2
3
 
3
4
  module ConcertoHardware
4
5
  # There is no important functionality at the module level.
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concerto_hardware
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: '0.3'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Concerto Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-01 00:00:00.000000000 Z
11
+ date: 2015-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  description: A Rails Engine for managing Bandshell-powered Concerto hardware
@@ -31,6 +31,9 @@ executables: []
31
31
  extensions: []
32
32
  extra_rdoc_files: []
33
33
  files:
34
+ - LICENSE
35
+ - README.rdoc
36
+ - Rakefile
34
37
  - app/assets/images/concerto_hardware/helpicon.png
35
38
  - app/assets/javascripts/concerto_hardware/application.js
36
39
  - app/assets/javascripts/concerto_hardware/players.js
@@ -54,13 +57,10 @@ files:
54
57
  - config/routes.rb
55
58
  - db/migrate/20121220000000_create_concerto_hardware_players.rb
56
59
  - db/migrate/20131127201048_add_updates_to_concerto_hardware_players.rb
60
+ - lib/concerto_hardware.rb
57
61
  - lib/concerto_hardware/engine.rb
58
62
  - lib/concerto_hardware/time_accessible.rb
59
63
  - lib/concerto_hardware/version.rb
60
- - lib/concerto_hardware.rb
61
- - LICENSE
62
- - Rakefile
63
- - README.rdoc
64
64
  - test/fixtures/players.yml
65
65
  - test/functional/players_controller_test.rb
66
66
  - test/unit/helpers/players_helper_test.rb
@@ -75,17 +75,17 @@ require_paths:
75
75
  - lib
76
76
  required_ruby_version: !ruby/object:Gem::Requirement
77
77
  requirements:
78
- - - '>='
78
+ - - ">="
79
79
  - !ruby/object:Gem::Version
80
80
  version: '0'
81
81
  required_rubygems_version: !ruby/object:Gem::Requirement
82
82
  requirements:
83
- - - '>='
83
+ - - ">="
84
84
  - !ruby/object:Gem::Version
85
85
  version: '0'
86
86
  requirements: []
87
87
  rubyforge_project:
88
- rubygems_version: 2.0.14
88
+ rubygems_version: 2.4.5
89
89
  signing_key:
90
90
  specification_version: 4
91
91
  summary: A Rails Engine for managing Bandshell-powered Concerto hardware