kodiak 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.
@@ -0,0 +1,38 @@
1
+ module Kodiak
2
+ class Generator
3
+
4
+ attr_accessor :options
5
+
6
+ def initialize(options)
7
+ @options = options
8
+ end
9
+
10
+ def generate
11
+ if config_exists? && ! options[:force]
12
+ Kodiak::Notification.new "Kodiak config already exists in this directory. Use --force to overwrite.\n", "failure"
13
+ elsif (!config_exists?) || (config_exists? && options[:force])
14
+ copy_config
15
+ end
16
+ end
17
+
18
+ # check to see if Kodiak.yaml already exists in directory
19
+ def config_exists?
20
+ File.exists? Kodiak::CONFIG_FILENAME
21
+ end
22
+
23
+ # copy sample Kodiak.yaml to directory
24
+ def copy_config
25
+ FileUtils.cp_r "#{Kodiak::CONFIG_PATH}/#{Kodiak::CONFIG_FILENAME}", "#{Kodiak::CONFIG_FILENAME}", :remove_destination => true
26
+
27
+ # if logs exist already, don't overwrite them. Not even in force mode. Never ever.
28
+ if not File.exists? Kodiak::LOG_FILENAME
29
+ FileUtils.cp_r "#{Kodiak::CONFIG_PATH}/#{Kodiak::LOG_FILENAME}", "#{Kodiak::LOG_FILENAME}", :remove_destination => true
30
+ end
31
+
32
+ Kodiak::Notification.new "Kodiak configuration created at #{Kodiak::CONFIG_FILENAME}\n", "success"
33
+ system("open #{Kodiak::CONFIG_FILENAME}")
34
+ exit
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,65 @@
1
+ require 'appscript'
2
+ require 'term/ansicolor'
3
+ include Term::ANSIColor
4
+
5
+ module Kodiak
6
+ class Notification
7
+
8
+ attr_accessor :growl, :application, :icon, :default_notifications, :notifications, :type, :message
9
+
10
+ def initialize(message, type = "message")
11
+ @message = message
12
+ @type = type
13
+
14
+ console_notify
15
+
16
+ if Config::CONFIG['target_os'] =~ /darwin/i
17
+ @growl = Appscript.app("GrowlHelperApp");
18
+
19
+ if @growl.is_running?
20
+ growl_register
21
+ growl_notify
22
+ end
23
+ end
24
+ end
25
+
26
+
27
+ def console_notify
28
+ case @type
29
+ when "success"
30
+ print @message.green
31
+ when "warning"
32
+ print @message.yellow
33
+ when "failure"
34
+ print @message.red
35
+ else
36
+ print @message.white
37
+ end
38
+ end
39
+
40
+
41
+ # trigger a growl notification
42
+ def growl_notify
43
+ options = { :title => @application,
44
+ :description => @message.gsub(/[\n]+/, ""),
45
+ :application_name => @application,
46
+ :image_from_location => @icon,
47
+ :sticky => false,
48
+ :priority => 0,
49
+ :with_name => notifications.first }
50
+ @growl.notify options
51
+ end
52
+
53
+
54
+ # register Kodiak as an application with Growl
55
+ def growl_register
56
+ @application = Kodiak::APP_NAME
57
+ @icon = "#{Kodiak::CONFIG_PATH}/#{Kodiak::CONFIG_ICON}"
58
+ @default_notifications = ["Kodiak Success"]
59
+ @notifications = ["Kodiak Success", "Kodiak Failure"]
60
+ @growl.register(:as_application => @application, :all_notifications => @notifications, :default_notifications => @default_notifications)
61
+ end
62
+
63
+
64
+ end
65
+ end
@@ -0,0 +1,129 @@
1
+ module Kodiak
2
+ class Transporter
3
+
4
+ attr_accessor :config, :options, :files, :pushed, :ignored
5
+
6
+ def initialize(config, options)
7
+ @config = config
8
+ @files = @config.files
9
+ @files = @config.files
10
+ @options = options
11
+ end
12
+
13
+
14
+ def transport(files = nil)
15
+ @pushed = []
16
+ @ignored = []
17
+ @files = files || @files
18
+ if @config.ftp?
19
+ ftp
20
+ else
21
+ local
22
+ end
23
+ end
24
+
25
+
26
+ def local
27
+ puts "\nPushing to [#{@options[:environment]}]"
28
+
29
+ @files.each do |file|
30
+
31
+ if @options[:force]
32
+ push file
33
+
34
+ elsif File.exists? file[:destination]
35
+ source_changed = File.ctime(file[:source])
36
+ destination_changed = File.ctime(file[:destination])
37
+
38
+ # check if destination is older than source
39
+ if (destination_changed <=> source_changed) == -1
40
+ push file
41
+ else
42
+ ignore file, "Destination file was newer than source."
43
+ end
44
+
45
+ else
46
+ push file
47
+ end
48
+ end
49
+
50
+ if ! @options[:quiet]
51
+ Kodiak::Notification.new "\nPushed #{@pushed.length} files, Ignored #{@ignored.length} files\n\n", "success"
52
+ else
53
+ puts "\nPushed #{@pushed.length} files, Ignored #{@ignored.length} files\n\n"
54
+ end
55
+
56
+ if @options[:verbose] && @ignored.length > 0
57
+ puts "Some files were ignored. Use --force to force overwrite.\n\n"
58
+ end
59
+
60
+ Kodiak.log :pushed => @pushed, :ignored => @ignored
61
+
62
+ end
63
+
64
+
65
+ def ftp
66
+ require 'net/ftp'
67
+ credentials = @config.ftp
68
+
69
+ puts "Connecting to #{credentials['server']}..."
70
+
71
+ Net::FTP.open credentials['server'] do |ftp|
72
+ ftp.login credentials['username'], credentials['password']
73
+ ftp.chdir credentials['path']
74
+
75
+ @files.each do |file|
76
+ source = file[:source]
77
+ destination = file[:destination]
78
+
79
+ if not File.directory? source
80
+ folders = destination.split("/")
81
+ filename = folders.pop
82
+
83
+ folders.each do |folder|
84
+ if not ftp.nlst.index(folder)
85
+ puts "- /#{folder} not found. Creating."
86
+ ftp.mkdir folder
87
+ end
88
+ puts "- opening directory /#{folder}"
89
+ ftp.chdir folder
90
+ end
91
+
92
+ puts "+ pushing #{filename}"
93
+ if File.directory? filename
94
+ ftp.mkdir filename
95
+ else
96
+ ftp.put source, filename
97
+ end
98
+ folders.length.times { ftp.chdir("..") }
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+
105
+ def push(file)
106
+ FileUtils.cp_r file[:source], file[:destination], :remove_destination => true
107
+
108
+ if @options[:verbose]
109
+ Kodiak::Notification.new "Pushed #{file[:source]} --> #{file[:destination]}\n"
110
+ else
111
+ puts " - Pushed #{file[:source]} --> #{file[:destination]}\n"
112
+ end
113
+
114
+ @pushed.push file
115
+ end
116
+
117
+ def ignore(file, reason)
118
+ file[:reason] = reason
119
+ if @options[:verbose]
120
+ Kodiak::Notification.new "Ignored #{file[:source]}\n - #{file[:reason]}\n"
121
+ else
122
+ puts "Ignored #{file[:source]}\n - #{file[:reason]}\n"
123
+ end
124
+
125
+ @ignored.push file
126
+ end
127
+
128
+ end
129
+ end
@@ -0,0 +1,29 @@
1
+ module Kodiak
2
+
3
+ def self.log(params={})
4
+ pushed = params[:pushed]
5
+ ignored = params[:ignored]
6
+
7
+ file = File.open("#{Kodiak::LOG_FILENAME}", "a+")
8
+
9
+ time = Time.now.strftime("%A, %m/%d/%Y at %I:%M:%3N %p")
10
+ message = "#{time} | #{Kodiak.user['name']} (#{Kodiak.user['email']})\n"
11
+ message += "---------------------------------------------------------------------------------\n"
12
+ message += "Pushed #{pushed.length} files and ignored #{ignored.length} files\n"
13
+ message += "---------------------------------------------------------------------------------\n"
14
+
15
+ pushed.each do |file|
16
+ message += "Pushed [#{file[:source]}] --> [#{file[:destination]}]\n"
17
+ end
18
+
19
+ ignored.each do |file|
20
+ message += "Ignored #{file[:source]} because #{file[:reason].downcase}\n"
21
+ end
22
+
23
+ message += "\n\n\n"
24
+
25
+ file.write(message)
26
+ file.close
27
+ end
28
+
29
+ end
@@ -0,0 +1,37 @@
1
+ require 'directory_watcher'
2
+
3
+ module Kodiak
4
+ class Watcher
5
+
6
+ attr_accessor :config, :options, :files
7
+
8
+ def initialize(config, options)
9
+ @config = config
10
+ @files = config.files
11
+ @options = options
12
+ watch
13
+ end
14
+
15
+ def watch
16
+ transporter = Kodiak::Transporter.new(config, options)
17
+
18
+ dw = []
19
+ @files.each do |file|
20
+ dw = DirectoryWatcher.new '.', :glob => file[:source], :pre_load => true
21
+ dw.add_observer do |*args|
22
+ args.each do |event|
23
+ if event.type == :stable then transporter.transport [file] end
24
+ end
25
+ end
26
+ dw.interval = 0.25 # polling interval
27
+ dw.stable = 2 # mutiple of interval for 'stable' events
28
+ dw.start
29
+ end
30
+
31
+ puts "Kodiak server started"
32
+ STDIN.gets
33
+ dw.stop
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,451 @@
1
+ // require utils.hash
2
+ // require jquery
3
+
4
+ var Application = Application || function(data){
5
+
6
+ var self = this;
7
+ var fxspeed = 200;
8
+ var hash = new Utils.Hash();
9
+ var $loading = $("#loading");
10
+
11
+ //
12
+
13
+ self.initialize = function(){
14
+ self.map = new Map(data.map, "map");
15
+ self.panels.init();
16
+ self.layers.init();
17
+ self.overlays.init();
18
+ self.observe();
19
+ return self;
20
+ }
21
+
22
+ //
23
+
24
+ self.observe = function(){
25
+
26
+ $("a.flyout-trigger").live('click',function(e){
27
+ e.preventDefault();
28
+ var href = $(this).attr("href");
29
+ var $remote = $(href);
30
+
31
+
32
+
33
+
34
+ if( $remote.is(':hidden') ){
35
+ $remote.siblings('.flyout').slideUp(fxspeed);
36
+ $remote.slideDown(fxspeed);
37
+ }
38
+ else {
39
+ $remote.slideUp(fxspeed);
40
+ }
41
+ });
42
+ return self;
43
+ }
44
+
45
+
46
+
47
+
48
+
49
+
50
+ //
51
+
52
+ self.panels = {
53
+
54
+ init : function(){
55
+ this.build();
56
+ this.observe();
57
+ },
58
+
59
+ build : function(){
60
+
61
+ if( hash.element() ) {
62
+ var $panel = $(hash.element());
63
+ self.panels.show($panel);
64
+ } else {
65
+ $panel = $('#panel .panel').eq(0);
66
+ self.panels.show($panel);
67
+ }
68
+
69
+ },
70
+
71
+ observe : function(){
72
+
73
+ hash.onChange( function(){
74
+ var $panel = $(hash.element());
75
+ self.panels.show($panel);
76
+ });
77
+
78
+ $('.hash-trigger').live('click', function(e){
79
+ e.preventDefault();
80
+ e.stopPropagation();
81
+ var href = $(this).attr("href");
82
+ hash.set(href);
83
+ });
84
+
85
+ $('.panel').live('click',function(e){
86
+ if ( $(this).hasClass("active") ) {
87
+ e.stopPropagation();
88
+
89
+ var id = $(this).attr("id");
90
+
91
+ if ( id ) {
92
+ hash.set(id);
93
+ }
94
+
95
+ } else {
96
+ return false;
97
+ }
98
+ });
99
+ },
100
+
101
+ show : function($panel){
102
+ var fxs = 200;
103
+ var animation = {};
104
+ var css = {};
105
+
106
+ if ( $panel.parents('.panel').length ) {
107
+ animation.opacity = 1;
108
+
109
+ if ( $panel.parents('.panel').length == 1 ){
110
+ animation.left = "80px";
111
+ }
112
+ else {
113
+ animation.left = "20px";
114
+ }
115
+
116
+ if( $panel.is(':hidden') ){
117
+ css.display = "block";
118
+ css.opacity = 0;
119
+ }
120
+ }
121
+
122
+ $panel.parents('.panel').each(function(){
123
+ var css = {
124
+ display : 'block',
125
+ opacity : 1
126
+ };
127
+ if ( $(this).parents('.panel').length == 1 ){
128
+ css.left = "80px";
129
+ }
130
+ else {
131
+ css.left = "0px";
132
+ }
133
+ $(this).css(css).addClass("inactive");
134
+ });
135
+
136
+ $panel.css(css).animate(animation, fxs, function(){
137
+ $panel.removeClass("inactive").addClass("active");
138
+ });
139
+
140
+ $panel.siblings('.panel').each(function(){
141
+ $(this).removeClass("active").addClass("inactive").fadeOut(fxs, function(){
142
+ $(this).css("left","-100%");
143
+ });
144
+ });
145
+
146
+ $panel.children('.panel').each(function(){
147
+ $(this).removeClass("active").addClass("inactive").fadeOut(fxs, function(){
148
+ $(this).css("left","-100%");
149
+ });
150
+ });
151
+ }
152
+
153
+ };
154
+
155
+ //
156
+
157
+ self.layers = {
158
+
159
+ init : function(){
160
+ this.build();
161
+ this.observe();
162
+ },
163
+
164
+ build : function(){
165
+
166
+ self.loader.start();
167
+
168
+ var layers = self.map.layers;
169
+ self.map.layers = {};
170
+
171
+ for ( var index in layers ) {
172
+ var layer = layers[index];
173
+ self.map.layers[layer.id] = new Layer(layer);
174
+ }
175
+
176
+ self.layers.refresh();
177
+ },
178
+
179
+
180
+ observe : function(){
181
+
182
+ $(".layer-toggle").live('click', function(e){
183
+ e.preventDefault();
184
+ var id = $(this).attr("rel");
185
+ var layer = self.map.layers[id];
186
+ self.layers.toggle(layer, $(this));
187
+ });
188
+
189
+ $('.delete-layer').live('click', function(e){
190
+ e.preventDefault();
191
+ e.stopPropagation();
192
+ var href = $(this).attr("href");
193
+ var id = $(this).attr("data-layer-id");
194
+ var layer = self.map.layers[id];
195
+ if (confirm("Are you sure?")) {
196
+ self.layers.remove(layer, href);
197
+ }
198
+ });
199
+
200
+ $('#new-layer form').submit(function(e){
201
+ e.preventDefault();
202
+ self.loader.start();
203
+ var $map_id = $(this).children("input[name='map_id']");
204
+ var $name = $(this).children("input[name='name']");
205
+
206
+ var data = {
207
+ map_id : $map_id.val(),
208
+ name : $name.val()
209
+ }
210
+
211
+ $.post("/api/layers/create", data,
212
+ function(layer) {
213
+ self.map.layers[layer.id] = new Layer(layer);
214
+ $('#new-layer').slideUp(fxspeed);
215
+ $name.val('');
216
+ self.layers.refresh();
217
+ }, 'json'
218
+ );
219
+
220
+ });
221
+
222
+ },
223
+
224
+
225
+ refresh : function(){
226
+ self.loader.start();
227
+
228
+ $("#layers > ul.nav").fadeOut(fxspeed, function(){
229
+ $(this).remove();
230
+ });
231
+
232
+ $("#layers > .panel").fadeOut(fxspeed, function(){
233
+ $(this).remove();
234
+ });
235
+
236
+ $.post("/api/layers/index", {},
237
+ function(response) {
238
+ $("#layers").append(response);
239
+ self.panels.build();
240
+ self.loader.stop();
241
+ }
242
+ );
243
+ },
244
+
245
+
246
+ toggle : function(layer, $element){
247
+
248
+ if ( layer.hidden ) {
249
+ layer.show();
250
+ $element.addClass('active');
251
+ }
252
+ else {
253
+ layer.hide();
254
+ $element.removeClass('active');
255
+ }
256
+
257
+ },
258
+
259
+ remove : function(layer, href){
260
+ self.loader.start();
261
+ layer.hide();
262
+ var url = "/api/layers/delete/" + layer.id;
263
+ $.post(url, {}, function(response){
264
+ self.loader.stop();
265
+ hash.set(href);
266
+ var $anchor = $("#layers > ul.nav > li > a[rel='" + layer.id + "']");
267
+ var $li = $anchor.parent('li');
268
+ $li.delay(fxspeed).fadeOut(fxspeed);
269
+ });
270
+ }
271
+
272
+ };
273
+
274
+ //
275
+
276
+ self.overlays = {
277
+
278
+ init : function(){
279
+ this.build();
280
+ this.observe();
281
+ },
282
+
283
+ build : function(){
284
+ for ( var index in self.map.layers ) {
285
+ var layer = self.map.layers[index];
286
+
287
+ console.log(layer);
288
+
289
+
290
+ var overlays = layer.overlays;
291
+
292
+ layer.overlays = {};
293
+
294
+ for ( var index in overlays ) {
295
+ var overlay = overlays[index];
296
+ switch ( overlay.type ) {
297
+ case 'polygon' :
298
+ layer.overlays[overlay.id] = new Polygon(overlay);
299
+ break;
300
+ case 'marker' :
301
+ layer.overlays[overlay.id] = new Marker(overlay);
302
+ break;
303
+ case 'line' :
304
+ layer.overlays[overlay.id] = new Line(overlay);
305
+ break;
306
+ }
307
+ }
308
+ }
309
+
310
+
311
+ },
312
+
313
+ observe : function(){
314
+
315
+ $(".draw-overlay").click(function(e){
316
+ e.preventDefault();
317
+
318
+ var layer_id = $(this).siblings("input[name='layer_id']").val();
319
+
320
+ overlay = map.layers[layer_id].addOverlay({
321
+ layer_id : layer_id,
322
+ points: [{ lat: 0, lng: 0 },{ lat: 0, lng: 0 }],
323
+ strokeColor: "#FF00FF",
324
+ strokeOpacity: 0,
325
+ strokeWeight: 0,
326
+ fillColor: "#F0F",
327
+ fillOpacity: 0.5
328
+ });
329
+
330
+ overlay.draw();
331
+ });
332
+
333
+ $(".clear-overlay").click(function(e){
334
+ e.preventDefault();
335
+ overlay.remove();
336
+ });
337
+
338
+ $(".save-overlay").click(function(e){
339
+ e.preventDefault();
340
+ var name = $(this).siblings("input[name='name']").val();
341
+ if ( name == "" ){
342
+ alert("Please provide a name for this overlay");
343
+ return false;
344
+ }
345
+ else {
346
+ overlay.name = name;
347
+ self.overlays.save(overlay);
348
+ }
349
+ });
350
+
351
+ },
352
+
353
+ save : function(overlay){
354
+ self.loader.start();
355
+
356
+ var data = {
357
+ name : overlay.name,
358
+ layer_id : overlay.data.layer_id
359
+ };
360
+
361
+ $.post("/api/overlays/create", data,
362
+ function(data) {
363
+ overlay.id = data.id;
364
+
365
+ var points = overlay.data.points;
366
+
367
+ for ( var index in points ) {
368
+ points[index].overlay_id = overlay.id;
369
+ }
370
+
371
+ $.post("/api/points/create", { points: points },
372
+ function(response) {
373
+ self.loader.stop();
374
+ }
375
+ );
376
+ }
377
+ );
378
+ },
379
+
380
+ remove : function(overlay){
381
+
382
+ }
383
+
384
+ };
385
+
386
+
387
+
388
+
389
+ //
390
+
391
+ self.loader = {
392
+
393
+ start : function(){
394
+ $loading.fadeIn(fxspeed);
395
+ },
396
+
397
+ stop : function(){
398
+ $loading.delay(500).fadeOut(fxspeed);
399
+ }
400
+
401
+ };
402
+
403
+ //
404
+
405
+
406
+
407
+
408
+ // self.map.canvas.setOptions({ draggableCursor: 'crosshair' });
409
+ //
410
+ // self.data.paths = [];
411
+ // self.data.points = [];
412
+ //
413
+ // google.maps.event.addListener(self.map.canvas, 'click', function(mdEvent) {
414
+ //
415
+ // google.maps.event.addListener(self.map.canvas, 'mousemove', function(event) {
416
+ // self.addPoint({ lat: event.latLng.lat(), lng: event.latLng.lng() });
417
+ // });
418
+ //
419
+ // google.maps.event.addListener(self.map.canvas, 'click', function(event) {
420
+ // google.maps.event.clearListeners(self.map.canvas);
421
+ // google.maps.event.clearListeners(self.polygon);
422
+ // });
423
+ //
424
+ // google.maps.event.addListener(self.polygon, 'mousemove', function(event) {
425
+ // self.addPoint({ lat: event.latLng.lat(), lng: event.latLng.lng() });
426
+ // });
427
+ //
428
+ // google.maps.event.addListener(self.polygon, 'click', function(event) {
429
+ // google.maps.event.clearListeners(map.canvas);
430
+ // google.maps.event.clearListeners(self.polygon);
431
+ // });
432
+ //
433
+ // });
434
+
435
+
436
+
437
+
438
+
439
+
440
+
441
+
442
+
443
+
444
+
445
+
446
+
447
+
448
+
449
+
450
+ return self.initialize();
451
+ };