scheduled_resource 0.0.1 → 0.0.2
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 +4 -4
- data/README.md +109 -44
- data/app/assets/javascripts/angular.js +16876 -0
- data/app/assets/javascripts/controllers.js +157 -0
- data/app/assets/javascripts/script.js +11 -0
- data/app/views/layouts/application.html.erb +70 -0
- data/app/views/schedule/index.html.erb +3 -0
- data/lib/assets/javascripts/justify_tweaks.js +3 -3
- data/lib/assets/javascripts/time_pix.js.coffee +3 -3
- data/lib/assets/javascripts/use_block.js.coffee +4 -4
- data/lib/scheduled_resource.rb +15 -15
- data/lib/scheduled_resource/version.rb +1 -1
- data/scheduled_resource.gemspec +4 -4
- metadata +86 -58
@@ -0,0 +1,157 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
// ============================================================================
|
4
|
+
// Hi-lock: ((" ?[T]o ?Do:.*" (0 'accent10 t)))
|
5
|
+
// Hi-lock: (("\\(^\\|\\W\\)\\*\\(\\w.*\\w\\)\\*\\(\\W\\|$\\)" (2 'accent3 t)))
|
6
|
+
// Hi-lock: end
|
7
|
+
// ============================================================================
|
8
|
+
|
9
|
+
/* Controllers */
|
10
|
+
|
11
|
+
function ResourceListCtrl($scope, $http) {
|
12
|
+
$.extend( $scope,
|
13
|
+
{
|
14
|
+
init_display_parms: function () {
|
15
|
+
TimePix.set_display_parms()
|
16
|
+
},
|
17
|
+
|
18
|
+
init_resources: function () {
|
19
|
+
$scope.init_display_parms()
|
20
|
+
|
21
|
+
$scope.rsrcs = UseBlock.rsrcs = TimePix.meta.rsrcs
|
22
|
+
$scope.res_tags = []; // ^^ Defines the order of rows
|
23
|
+
$scope.rsrcs.forEach( function(rsrc) {
|
24
|
+
$scope.res_tags.push( rsrc.tag )
|
25
|
+
})
|
26
|
+
$scope.use_block_list_Ctls = {} // To access lower-level scopes later on
|
27
|
+
|
28
|
+
setTimeout( TimePix.scroll_to_tlo, 100 )
|
29
|
+
setTimeout( TimePix.set_time_cursor, 1000 )
|
30
|
+
setTimeout( TimePix.scroll_monitor, 100 )
|
31
|
+
},
|
32
|
+
|
33
|
+
get_data: function (t1, t2, inc) {
|
34
|
+
return $http.get( $scope.make_url(t1, t2, inc) ).
|
35
|
+
|
36
|
+
success( function(data) {
|
37
|
+
TimePix.merge_metadata(data)
|
38
|
+
delete data.meta
|
39
|
+
$scope.json_data = data // Park this here until we consume it.
|
40
|
+
|
41
|
+
if (! inc) { $scope.init_resources($scope) }
|
42
|
+
$scope.busy = false;
|
43
|
+
}). // success
|
44
|
+
|
45
|
+
error( function(data, status, headers, config) {
|
46
|
+
console.log( '\nstatus: ' + status +
|
47
|
+
'\nheaders(): ' + headers() +
|
48
|
+
'\nconfig: ' + config
|
49
|
+
)
|
50
|
+
console.debug( data.meta )
|
51
|
+
$scope.busy = false;
|
52
|
+
}) // error
|
53
|
+
},
|
54
|
+
|
55
|
+
make_url: function (t1, t2, inc) {
|
56
|
+
var url = '/schedule.json'
|
57
|
+
if (t1 || t2 || inc)
|
58
|
+
url += '?t1=' + t1 + '&t2=' + t2 + '&inc=' + inc
|
59
|
+
return url
|
60
|
+
},
|
61
|
+
|
62
|
+
rq_data: function(t1, t2, inc) {
|
63
|
+
if (! $scope.busy ) {
|
64
|
+
$scope.busy = true;
|
65
|
+
$scope.get_data( t1, t2, inc ).
|
66
|
+
success( function(data) {
|
67
|
+
Object.keys($scope.json_data).forEach( function(key) {
|
68
|
+
var controller = $scope.use_block_list_Ctls[key] // To Do: Better mis-configuration response
|
69
|
+
if( ! controller ) {
|
70
|
+
console.log( "No key " + key + " in " +
|
71
|
+
$scope.use_block_list_Ctls );
|
72
|
+
return
|
73
|
+
}
|
74
|
+
var blocks = $scope.json_data[key]
|
75
|
+
controller.add_blocks( controller, blocks ) // To Do: Better mis-configuration response
|
76
|
+
})
|
77
|
+
|
78
|
+
}); // errors handled above in get_data
|
79
|
+
}
|
80
|
+
},
|
81
|
+
|
82
|
+
more_data: function() {
|
83
|
+
$scope.rq_data( TimePix.thi, TimePix.next_hi(), 'hi' )
|
84
|
+
},
|
85
|
+
|
86
|
+
less_data: function() {
|
87
|
+
$scope.rq_data( TimePix.next_lo(), TimePix.tlo, 'lo' )
|
88
|
+
}
|
89
|
+
});
|
90
|
+
window.RsrcListCtrlScope = $scope;
|
91
|
+
$scope.get_data();
|
92
|
+
} // end ResourceListCtrl
|
93
|
+
ResourceListCtrl.$inject = ['$scope', '$http'];
|
94
|
+
|
95
|
+
|
96
|
+
function ab (o) { return angular.bind( o, o.process ) }
|
97
|
+
|
98
|
+
var process_fns = {
|
99
|
+
Station: ab(StationUseBlock),
|
100
|
+
ZTimeHeaderDay: ab(ZTimeHeaderDayUseBlock),
|
101
|
+
ZTimeHeaderHour: ab(ZTimeHeaderHourUseBlock)
|
102
|
+
}
|
103
|
+
|
104
|
+
|
105
|
+
function UseBlockListCtrl($scope) {
|
106
|
+
|
107
|
+
$.extend( $scope, {
|
108
|
+
|
109
|
+
add_blocks: function ( $scope, blocks ) {
|
110
|
+
var how = 'push'
|
111
|
+
if (TimePix.inc == 'lo') {
|
112
|
+
how = 'unshift'
|
113
|
+
blocks.reverse()
|
114
|
+
}
|
115
|
+
if( ! blocks ) { return } // Why bother with this?
|
116
|
+
blocks.forEach( function(block) {
|
117
|
+
$scope.insert_block( $scope.process_fn(block.blk), how )
|
118
|
+
})
|
119
|
+
},
|
120
|
+
|
121
|
+
insert_block: function ( block, how ) {
|
122
|
+
$scope.use_blocks[how]( block )
|
123
|
+
}
|
124
|
+
});
|
125
|
+
|
126
|
+
|
127
|
+
$scope.use_blocks = [];
|
128
|
+
|
129
|
+
var resourceTag = $scope.res_tag,
|
130
|
+
blocks = $scope.json_data[ resourceTag ],
|
131
|
+
rsrc_kind = resourceTag.split('_')[0];
|
132
|
+
|
133
|
+
$scope.process_fn = process_fns[rsrc_kind];
|
134
|
+
if (! $scope.process_fn) {
|
135
|
+
console.log( 'Skipping use blocks with tag ' + resourceTag + ', Kind ' + rsrc_kind )
|
136
|
+
return null
|
137
|
+
}
|
138
|
+
|
139
|
+
$scope.use_block_list_Ctls[resourceTag] = $scope
|
140
|
+
|
141
|
+
$scope.add_blocks( $scope, blocks )
|
142
|
+
}
|
143
|
+
UseBlockListCtrl.$inject = ['$scope'];
|
144
|
+
|
145
|
+
|
146
|
+
function UseBlockCtrl($scope) {
|
147
|
+
var block = $scope.block // Just for debugger
|
148
|
+
}
|
149
|
+
UseBlockCtrl.$inject = ['$scope'];
|
150
|
+
|
151
|
+
|
152
|
+
function LabelListCtrl($scope) {
|
153
|
+
var tag = $scope.res_tag
|
154
|
+
UseBlock.rsrcs[tag] // (?)
|
155
|
+
}
|
156
|
+
LabelListCtrl.$inject = ['$scope'];
|
157
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
// declare a module
|
2
|
+
var srAppModule = angular.module('srApp', []);
|
3
|
+
|
4
|
+
// Configure the module. Create some filters.
|
5
|
+
srAppModule.filter('style_geo', function() {
|
6
|
+
return angular.bind(TimePix, TimePix.style_geo);
|
7
|
+
});
|
8
|
+
|
9
|
+
srAppModule.filter('rowKind', function() {
|
10
|
+
return angular.bind(TimePix, TimePix.row_kind);
|
11
|
+
});
|
@@ -0,0 +1,70 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang='en' ng-app='srApp'>
|
3
|
+
<head>
|
4
|
+
<title>Scheduled Resource Example <%= controller.action_name %></title>
|
5
|
+
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
|
6
|
+
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<div class="container">
|
11
|
+
|
12
|
+
<%= yield %>
|
13
|
+
|
14
|
+
<!--Body content-->
|
15
|
+
<div class="row"> <!-- -fluid -->
|
16
|
+
<div id="schedule-container"
|
17
|
+
ng-controller="ResourceListCtrl">
|
18
|
+
|
19
|
+
<div id="labels-container">
|
20
|
+
<div id="resource-labels">
|
21
|
+
<div ng-controller="LabelListCtrl"
|
22
|
+
ng-repeat="rsrc in rsrcs"
|
23
|
+
class="rsrcRow {{ rsrc.tag | rowKind }}row">
|
24
|
+
|
25
|
+
<div class="rsrclabel">
|
26
|
+
<img ng-src="/assets/{{ rsrc.label }}.jpg" title="{{ rsrc.title }}" />
|
27
|
+
<div class="filter"> </div>
|
28
|
+
<div class="label-text">{{rsrc.label}}</div>
|
29
|
+
</div>
|
30
|
+
|
31
|
+
</div>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div id="timespans-container">
|
36
|
+
<div id="scrolling-container">
|
37
|
+
<div id="positioned-container">
|
38
|
+
<div id="current-time-cursor"> </div>
|
39
|
+
|
40
|
+
<div ng-repeat="res_tag in res_tags"
|
41
|
+
ng-controller="UseBlockListCtrl"
|
42
|
+
class="rsrcRow {{ res_tag | rowKind }}row">
|
43
|
+
|
44
|
+
<div class="timespan">
|
45
|
+
<div ng-repeat="block in use_blocks"
|
46
|
+
ng-controller="UseBlockCtrl"
|
47
|
+
class="{{ block.css_classes }} blockdiv"
|
48
|
+
style="{{ block | style_geo }} ">
|
49
|
+
|
50
|
+
<div class="text_locator">
|
51
|
+
<a href="" ng-bind-html-unsafe="block.label"></a>
|
52
|
+
</div>
|
53
|
+
|
54
|
+
<!-- app/views/schedule/_block_internal.html.erb -->
|
55
|
+
</div>
|
56
|
+
</div>
|
57
|
+
</div>
|
58
|
+
|
59
|
+
</div>
|
60
|
+
</div>
|
61
|
+
</div>
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
</div> <!-- end ResourceListCtrl -->
|
66
|
+
</div>
|
67
|
+
|
68
|
+
</div>
|
69
|
+
</body>
|
70
|
+
</html>
|
@@ -19,14 +19,14 @@
|
|
19
19
|
// changes to the '.text_locator' with a little randomness thrown in.
|
20
20
|
|
21
21
|
// ToDo: Convert this to an object w/ methods, for better encapsulation.
|
22
|
-
|
23
|
-
// Sole exported function:
|
22
|
+
|
23
|
+
// Sole exported function:
|
24
24
|
function filter_justify_tweaks(sc) {
|
25
25
|
var scrollLeft = sc.scrollLeft()
|
26
26
|
|
27
27
|
// Don't repeat the calculation unnecessarily....
|
28
28
|
if ( filter_justify_tweaks.old_srcoll == scrollLeft ) return
|
29
|
-
filter_justify_tweaks.old_srcoll = scrollLeft
|
29
|
+
filter_justify_tweaks.old_srcoll = scrollLeft
|
30
30
|
|
31
31
|
do_justify_tweaks( sc, scrollLeft )
|
32
32
|
}
|
@@ -8,7 +8,7 @@ class @TimePix # Ultimately, an angular $service
|
|
8
8
|
@scroll_container().css( 'width', @pixWindow + 'px' )
|
9
9
|
$('#scrollbar-hider').css('width', @pixWindow + 61 + 'px' )
|
10
10
|
|
11
|
-
|
11
|
+
|
12
12
|
@baseTime: 0
|
13
13
|
@timeWindow: (3 * 3600)
|
14
14
|
@pixWindow: 750 # Matching width of #scrolling-container
|
@@ -42,7 +42,7 @@ class @TimePix # Ultimately, an angular $service
|
|
42
42
|
@style_geo: (block) ->
|
43
43
|
[s, e] = [block.starttime, block.endtime] # per margins V
|
44
44
|
"left: #{@secs_to_pix_scale(s - @baseTime)}px; " +
|
45
|
-
"width: #{@secs_to_pix_scale(e-s)-4}px;"
|
45
|
+
"width: #{@secs_to_pix_scale(e-s)-4}px;"
|
46
46
|
|
47
47
|
@row_kind: (tag) -> # may/may not belong here.
|
48
48
|
tag.split('_')[0]
|
@@ -67,7 +67,7 @@ class @TimePix # Ultimately, an angular $service
|
|
67
67
|
@scroll_to_ux_time( @thi - @timeWindow )
|
68
68
|
|
69
69
|
@ux_time_of_pix: (x) ->
|
70
|
-
@pix_to_secs(x)
|
70
|
+
@pix_to_secs(x)
|
71
71
|
|
72
72
|
@scroll_to_tlo: => # bound
|
73
73
|
@scroll_to_ux_time @tlo
|
@@ -12,7 +12,7 @@ class @ZTimeHeaderDayUseBlock extends UseBlock
|
|
12
12
|
|
13
13
|
@label: (block) ->
|
14
14
|
block.label = block.title
|
15
|
-
|
15
|
+
|
16
16
|
@css_classes: (block) ->
|
17
17
|
# Could just as well come from server.
|
18
18
|
classes = 'ZTimeHeaderDayRow '
|
@@ -30,7 +30,7 @@ class @ZTimeHeaderHourUseBlock extends UseBlock
|
|
30
30
|
|
31
31
|
@label: (block) ->
|
32
32
|
block.label = block.title
|
33
|
-
|
33
|
+
|
34
34
|
@css_classes: (block) ->
|
35
35
|
# Could just as well come from server.
|
36
36
|
# classes = 'ZTimeHeaderHourRow '
|
@@ -42,7 +42,7 @@ class @ZTimeHeaderHourUseBlock extends UseBlock
|
|
42
42
|
|
43
43
|
|
44
44
|
|
45
|
-
# Uses these fields of block: title, subtitle, category, category_type,
|
45
|
+
# Uses these fields of block: title, subtitle, category, category_type,
|
46
46
|
# Sets these fields of block: label, css_classes
|
47
47
|
class @StationUseBlock extends UseBlock
|
48
48
|
constructor: -> nil
|
@@ -79,7 +79,7 @@ class @StationUseBlock extends UseBlock
|
|
79
79
|
@css_class_search: (category) ->
|
80
80
|
for key, regex of @categories
|
81
81
|
return ('cat_' + key) if regex.test category
|
82
|
-
'cat_Unknown'
|
82
|
+
'cat_Unknown'
|
83
83
|
|
84
84
|
|
85
85
|
@memo: {}
|
data/lib/scheduled_resource.rb
CHANGED
@@ -20,7 +20,7 @@ require 'z_time_label_hour'
|
|
20
20
|
# Example: A Room (resource) is scheduled for a meeting (resource use block)
|
21
21
|
# titled "Weekly Staff Meeting" tomorrow from 9am to 11am.
|
22
22
|
#
|
23
|
-
# Class
|
23
|
+
# Class ScheduledResource manages class names, id's and labels for a
|
24
24
|
# schedule. An instance ties together:
|
25
25
|
#
|
26
26
|
# 1. A resource class (eg Room),
|
@@ -67,19 +67,19 @@ class ScheduledResource
|
|
67
67
|
|
68
68
|
class_attribute :config
|
69
69
|
|
70
|
-
# (
|
70
|
+
# (ScheduledResource protocol) Returns a hash where each key is an
|
71
71
|
# <tt>rid</tt> and the value is an array of resource use
|
72
72
|
# blocks in the interval <tt>t1...t2</tt>, ordered by
|
73
73
|
# <tt>starttime</tt>.
|
74
74
|
#
|
75
|
-
# What <em>in</em> means depends on <em>inc</em>. If inc(remental) is
|
75
|
+
# What <em>in</em> means depends on <em>inc</em>. If inc(remental) is
|
76
76
|
# false, the client is building the interval from scratch. If "hi", it is
|
77
77
|
# an addition to an existing interval on the high side. Similarly
|
78
78
|
# for "lo". This is to avoid re-transmitting blocks that span the
|
79
79
|
# current time boundaries on the client.
|
80
80
|
#
|
81
81
|
# Here the resource is a channel and the use blocks are programs.
|
82
|
-
#
|
82
|
+
#
|
83
83
|
# ==== Parameters
|
84
84
|
# * <tt>rids</tt> - A list of schedules resource ids (strings).
|
85
85
|
# * <tt>t1</tt> - Start time.
|
@@ -102,19 +102,19 @@ class ScheduledResource
|
|
102
102
|
blockss
|
103
103
|
end
|
104
104
|
|
105
|
-
|
105
|
+
|
106
106
|
# ==== Parameters
|
107
107
|
# * <tt>name</tt> - The class name (string) of a schedule resource.
|
108
108
|
#
|
109
109
|
# ==== Returns
|
110
110
|
# * <tt>Class</tt> - The class representing the <em>use</em> of that resource for an interval of time.
|
111
111
|
def self.block_class_for_resource_name( name )
|
112
|
-
config[:block_class_for_resource_kind][name]
|
112
|
+
config[:block_class_for_resource_kind][name].constantize
|
113
113
|
end
|
114
114
|
|
115
115
|
|
116
116
|
# ==== Returns
|
117
|
-
# * <tt>Array[
|
117
|
+
# * <tt>Array[ScheduledResource]</tt> - List of configured ScheduledResources.
|
118
118
|
def self.resource_list; config[:all_resources] end
|
119
119
|
|
120
120
|
# ==== Returns
|
@@ -166,8 +166,8 @@ class ScheduledResource
|
|
166
166
|
}
|
167
167
|
yml = YAML.load_file CONFIG_FILE
|
168
168
|
|
169
|
-
yml['ResourceKinds'].each do |key, val| # {"Channel" =>
|
170
|
-
config[:block_class_for_resource_kind][key] =
|
169
|
+
yml['ResourceKinds'].each do |key, val| # {"Channel" => "Program"...}
|
170
|
+
config[:block_class_for_resource_kind][key] = val # class name (string)
|
171
171
|
end
|
172
172
|
|
173
173
|
if (rkls = yml['Resources']) # Resource Kind Lists, eg
|
@@ -185,12 +185,12 @@ class ScheduledResource
|
|
185
185
|
config[:time_range_min] = t0 ? (eval t0) : (Time.now - 1.week)
|
186
186
|
|
187
187
|
tn = yml['timeRangeMax']
|
188
|
-
config[:time_range_max] = tn ? (eval tn) : (Time.now
|
188
|
+
config[:time_range_max] = tn ? (eval tn) : (Time.now + 1.week)
|
189
189
|
|
190
190
|
config
|
191
191
|
end
|
192
192
|
|
193
|
-
|
193
|
+
|
194
194
|
def self.add_resources(rsrcs)
|
195
195
|
rs = config[:all_resources]
|
196
196
|
rsrcs.each{ |rsrc| rs.include?( rsrc ) || rs << rsrc }
|
@@ -236,16 +236,16 @@ class ScheduledResource
|
|
236
236
|
def kind() @tag.sub( /_.*/, '' ) end
|
237
237
|
|
238
238
|
# ==== Returns
|
239
|
-
# * <tt>String</tt> - The <tt>rid</tt> (abstract id) of the
|
239
|
+
# * <tt>String</tt> - The <tt>rid</tt> (abstract id) of the ScheduledResource.
|
240
240
|
def sub_id() @tag.sub( /.*_/, '' ) end
|
241
241
|
|
242
242
|
def to_s() # :nodoc:
|
243
243
|
@tag
|
244
|
-
end
|
244
|
+
end
|
245
245
|
|
246
246
|
def inspect() # :nodoc:
|
247
|
-
"<#
|
248
|
-
end
|
247
|
+
"<#ScheduledResource \"#{@tag}\">"
|
248
|
+
end
|
249
249
|
|
250
250
|
attr_accessor :label, :title
|
251
251
|
def label(); @label || @tag end
|
data/scheduled_resource.gemspec
CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = ScheduledResource::VERSION
|
9
9
|
spec.authors = ["Mike Cannon"]
|
10
10
|
spec.email = ["michael.j.cannon@gmail.com"]
|
11
|
-
spec.summary = %q{
|
11
|
+
spec.summary = %q{Display how something is used over time.}
|
12
12
|
spec.description = %Q{== README.md:\n#{IO.read 'README.md'}}
|
13
|
-
spec.homepage = ""
|
13
|
+
spec.homepage = "http://github.com/emeyekayee/scheduled_resource"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
@@ -18,8 +18,8 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "rails"
|
22
|
-
spec.add_dependency "coffee-rails"
|
21
|
+
spec.add_dependency "rails", "~> 4.2"
|
22
|
+
spec.add_dependency "coffee-rails", "~> 4.1"
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.7"
|
24
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
25
25
|
end
|