watch_tower 0.0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. data/.gitignore +10 -0
  2. data/.todo +33 -0
  3. data/.travis.yml +14 -0
  4. data/Gemfile +43 -0
  5. data/Guardfile +25 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +38 -0
  8. data/Rakefile +8 -0
  9. data/TODO +17 -0
  10. data/bin/watchtower +10 -0
  11. data/ci/adapters/jruby-mysql.yml +8 -0
  12. data/ci/adapters/jruby-postgresql.yml +6 -0
  13. data/ci/adapters/jruby-sqlite.yml +6 -0
  14. data/ci/adapters/ruby-mysql.yml +8 -0
  15. data/ci/adapters/ruby-postgresql.yml +6 -0
  16. data/ci/adapters/ruby-sqlite.yml +6 -0
  17. data/ci/travis.rb +102 -0
  18. data/lib/watch_tower.rb +60 -0
  19. data/lib/watch_tower/appscript.rb +22 -0
  20. data/lib/watch_tower/cli.rb +15 -0
  21. data/lib/watch_tower/cli/.gitkeep +0 -0
  22. data/lib/watch_tower/cli/install.rb +63 -0
  23. data/lib/watch_tower/cli/open.rb +24 -0
  24. data/lib/watch_tower/cli/start.rb +140 -0
  25. data/lib/watch_tower/config.rb +38 -0
  26. data/lib/watch_tower/core_ext.rb +4 -0
  27. data/lib/watch_tower/core_ext/.gitkeep +0 -0
  28. data/lib/watch_tower/editor.rb +17 -0
  29. data/lib/watch_tower/editor/.gitkeep +0 -0
  30. data/lib/watch_tower/editor/base_appscript.rb +34 -0
  31. data/lib/watch_tower/editor/base_ps.rb +6 -0
  32. data/lib/watch_tower/editor/textmate.rb +17 -0
  33. data/lib/watch_tower/editor/xcode.rb +22 -0
  34. data/lib/watch_tower/errors.rb +25 -0
  35. data/lib/watch_tower/eye.rb +79 -0
  36. data/lib/watch_tower/project.rb +14 -0
  37. data/lib/watch_tower/project/.gitkeep +0 -0
  38. data/lib/watch_tower/project/any_based.rb +22 -0
  39. data/lib/watch_tower/project/git_based.rb +86 -0
  40. data/lib/watch_tower/project/init.rb +38 -0
  41. data/lib/watch_tower/project/path_based.rb +144 -0
  42. data/lib/watch_tower/server.rb +62 -0
  43. data/lib/watch_tower/server/.gitkeep +0 -0
  44. data/lib/watch_tower/server/app.rb +37 -0
  45. data/lib/watch_tower/server/assets/images/WatchTower.jpg +0 -0
  46. data/lib/watch_tower/server/assets/images/percentage.png +0 -0
  47. data/lib/watch_tower/server/assets/javascripts/application.js +3 -0
  48. data/lib/watch_tower/server/assets/javascripts/percentage.coffee +8 -0
  49. data/lib/watch_tower/server/assets/stylesheets/application.css +7 -0
  50. data/lib/watch_tower/server/assets/stylesheets/global.sass +71 -0
  51. data/lib/watch_tower/server/assets/stylesheets/project.sass +59 -0
  52. data/lib/watch_tower/server/configurations.rb +10 -0
  53. data/lib/watch_tower/server/configurations/asset.rb +43 -0
  54. data/lib/watch_tower/server/database.rb +105 -0
  55. data/lib/watch_tower/server/db/migrate/001_create_projects.rb +15 -0
  56. data/lib/watch_tower/server/db/migrate/002_create_files.rb +16 -0
  57. data/lib/watch_tower/server/db/migrate/003_create_time_entries.rb +12 -0
  58. data/lib/watch_tower/server/db/migrate/004_create_durations.rb +14 -0
  59. data/lib/watch_tower/server/db/migrate/005_add_hash_to_time_entries.rb +6 -0
  60. data/lib/watch_tower/server/db/migrate/006_add_hash_to_files.rb +6 -0
  61. data/lib/watch_tower/server/decorator.rb +21 -0
  62. data/lib/watch_tower/server/decorator/application_decorator.rb +91 -0
  63. data/lib/watch_tower/server/decorator/file_decorator.rb +38 -0
  64. data/lib/watch_tower/server/decorator/project_decorator.rb +51 -0
  65. data/lib/watch_tower/server/helpers.rb +13 -0
  66. data/lib/watch_tower/server/helpers/asset.rb +29 -0
  67. data/lib/watch_tower/server/helpers/improved_partials.rb +41 -0
  68. data/lib/watch_tower/server/models/duration.rb +11 -0
  69. data/lib/watch_tower/server/models/file.rb +31 -0
  70. data/lib/watch_tower/server/models/project.rb +17 -0
  71. data/lib/watch_tower/server/models/time_entry.rb +64 -0
  72. data/lib/watch_tower/server/public/assets/WatchTower-4d6de11e1bd34165ad91ac46fb711bf3.jpg +0 -0
  73. data/lib/watch_tower/server/public/assets/application-7829b53b5ece1a16d22dc3d00f329023.css +107 -0
  74. data/lib/watch_tower/server/public/assets/application-e0e6b7731aade460f680331e65cf0682.js +9359 -0
  75. data/lib/watch_tower/server/public/assets/percentage-d8589e21a5fc85d32a445f531ff8ab95.png +0 -0
  76. data/lib/watch_tower/server/vendor/assets/javascripts/jquery-ui.js +11729 -0
  77. data/lib/watch_tower/server/vendor/assets/javascripts/jquery.js +8981 -0
  78. data/lib/watch_tower/server/vendor/assets/javascripts/jquery_ujs.js +363 -0
  79. data/lib/watch_tower/server/views/.gitkeep +0 -0
  80. data/lib/watch_tower/server/views/_file.haml +9 -0
  81. data/lib/watch_tower/server/views/_project.haml +13 -0
  82. data/lib/watch_tower/server/views/index.haml +7 -0
  83. data/lib/watch_tower/server/views/layout.haml +32 -0
  84. data/lib/watch_tower/server/views/project.haml +12 -0
  85. data/lib/watch_tower/templates/config.yml +146 -0
  86. data/lib/watch_tower/templates/watchtower.plist +23 -0
  87. data/lib/watch_tower/version.rb +8 -0
  88. data/spec/factories.rb +45 -0
  89. data/spec/spec_helper.rb +26 -0
  90. data/spec/support/active_record.rb +44 -0
  91. data/spec/support/factory_girl.rb +6 -0
  92. data/spec/support/launchy.rb +3 -0
  93. data/spec/support/sinatra.rb +10 -0
  94. data/spec/support/timecop.rb +7 -0
  95. data/spec/watch_tower/appscript_spec.rb +6 -0
  96. data/spec/watch_tower/cli/install_spec.rb +16 -0
  97. data/spec/watch_tower/cli/open_spec.rb +14 -0
  98. data/spec/watch_tower/cli/start_spec.rb +17 -0
  99. data/spec/watch_tower/cli_spec.rb +15 -0
  100. data/spec/watch_tower/config_spec.rb +25 -0
  101. data/spec/watch_tower/editor/textmate_spec.rb +43 -0
  102. data/spec/watch_tower/editor/xcode_spec.rb +43 -0
  103. data/spec/watch_tower/editor_spec.rb +19 -0
  104. data/spec/watch_tower/eye_spec.rb +130 -0
  105. data/spec/watch_tower/project/git_based_spec.rb +131 -0
  106. data/spec/watch_tower/project/path_based_spec.rb +111 -0
  107. data/spec/watch_tower/project_spec.rb +82 -0
  108. data/spec/watch_tower/server/app_spec.rb +186 -0
  109. data/spec/watch_tower/server/decorator/project_decorator_spec.rb +60 -0
  110. data/spec/watch_tower/server/models/file_spec.rb +284 -0
  111. data/spec/watch_tower/server/models/project_spec.rb +165 -0
  112. data/spec/watch_tower/server/models/time_entry_spec.rb +37 -0
  113. data/spec/watch_tower/server_spec.rb +4 -0
  114. data/watch_tower.gemspec +80 -0
  115. metadata +450 -0
File without changes
@@ -0,0 +1,37 @@
1
+ # Sinatra
2
+ require 'sinatra'
3
+
4
+ module WatchTower
5
+ module Server
6
+ class App < ::Sinatra::Application
7
+ # Helper
8
+ include Helpers::ImprovedPartials
9
+ include Helpers::Asset
10
+
11
+ # Include Decorator
12
+ include Decorator
13
+
14
+ # Configurations
15
+ include Configurations::Asset
16
+
17
+ # Routes
18
+ paths :root => '/'
19
+ paths :project => '/project/:id'
20
+
21
+ # The index action
22
+ get :root do
23
+ @title = "Projects"
24
+ @projects = ProjectDecorator.decorate(Project.worked_on)
25
+
26
+ haml :index
27
+ end
28
+
29
+ get :project do
30
+ @project = ProjectDecorator.find(params[:id])
31
+ @title = "Project - #{@project.name.camelcase}"
32
+
33
+ haml :project
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ //= require jquery
2
+ //= require jquery_ujs
3
+ //= require_tree .
@@ -0,0 +1,8 @@
1
+ animateGrowth = (domId, width) ->
2
+ ($ domId).attr('width', width)
3
+
4
+
5
+ jQuery ->
6
+ ($ '.percentage_img').each (index, element) ->
7
+ width = ($ element).attr('data-width')
8
+ animateGrowth(element, width * 3)
@@ -0,0 +1,7 @@
1
+ /*
2
+ * This is a manifest file that'll automatically include all the stylesheets available in this directory
3
+ * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
4
+ * the top of the compiled file, but it's generally better to create a new file per style scope.
5
+ *= require_self
6
+ *= require_tree .
7
+ */
@@ -0,0 +1,71 @@
1
+ $footer_text_color: #000
2
+ $footer_bg: #D6AFAF
3
+ $link_color: +darken($footer_bg, 20%)
4
+
5
+ h1
6
+ font-size: 2em
7
+ h2
8
+ font-size: 1em
9
+
10
+ #logo
11
+ a
12
+ color: #000
13
+ text-decoration: none
14
+
15
+ // Background stylesheet
16
+ display: block
17
+ // TODO: Very bad bad bad idea to hardcode assets, how can we reference an asset from sass ?
18
+ background: url('WatchTower-4d6de11e1bd34165ad91ac46fb711bf3.jpg') no-repeat
19
+ width: 390px
20
+ height: 94px
21
+
22
+ &:visited, &:hover
23
+ text-decoration: none
24
+
25
+ h1
26
+ float: left
27
+ margin-top: 30px
28
+ margin-left: 180px
29
+
30
+ .clearfix
31
+ clear: both
32
+
33
+ a
34
+ color: $link_color
35
+ text-decoration: none
36
+
37
+ &:hover, &:visited
38
+ text-decoration: none
39
+
40
+ body
41
+ background: #f7f7f7
42
+ color: #000
43
+ font-family: Arial, Helvetica, sans-serif
44
+
45
+ #wrapper
46
+ width: 960px
47
+ margin: 0 auto
48
+
49
+ #main
50
+ border: 1px solid #cdcdcd
51
+ -webkit-border-radius: 5px
52
+ -moz-border-radius: 5px
53
+ border-radius: 5px
54
+ padding: 10px
55
+ min-height: 200px
56
+ background: #fff
57
+
58
+ #footer
59
+ width: 960px
60
+ text-align: center
61
+ background: $footer_bg
62
+ color: $footer_text_color
63
+ padding: 5px 0
64
+ font-size: 12px
65
+
66
+ a
67
+ color: $footer_text_color
68
+ text-decoration: none
69
+
70
+ &:visited, &:hover
71
+ text-decoration: none
@@ -0,0 +1,59 @@
1
+ =project_name
2
+ float: left
3
+ width: 200px
4
+
5
+ =percentage
6
+ width: 310px
7
+ float: left
8
+ .percentage_img
9
+ height: 20px
10
+
11
+ =elapsed
12
+ float: left
13
+
14
+ =header_text
15
+ font-size: 20px
16
+ text-decoration: underline
17
+
18
+ #projects
19
+ header
20
+ .name
21
+ +project_name
22
+ +header_text
23
+
24
+ .percentage
25
+ +percentage
26
+ +header_text
27
+ .elapsed
28
+ +elapsed
29
+ +header_text
30
+
31
+ .project
32
+ .name
33
+ +project_name
34
+ .percentage_img_container
35
+ +percentage
36
+ .elapsed
37
+ +elapsed
38
+
39
+ #project
40
+ #files
41
+ header
42
+ .path
43
+ +header_text
44
+ float: left
45
+ width: 600px
46
+ .elapsed
47
+ +header_text
48
+ float: left
49
+
50
+ .path
51
+ float: left
52
+ width: 600px
53
+ .elapsed
54
+ float: left
55
+ .percentage_img_container
56
+ width: 310px
57
+ float: left
58
+ .percentage_img
59
+ height: 20px
@@ -0,0 +1,10 @@
1
+ module WatchTower
2
+ module Server
3
+ module Configurations
4
+ extend ::ActiveSupport::Autoload
5
+
6
+ # Sinatra configurations
7
+ autoload :Asset
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,43 @@
1
+ # Asset Pipeline
2
+ require 'coffee-script'
3
+ require 'uglifier'
4
+ require 'sass'
5
+ require 'sprockets'
6
+
7
+ module WatchTower
8
+ module Server
9
+ module Configurations
10
+ module Asset
11
+ def self.included(base)
12
+ base.class_eval <<-END, __FILE__, __LINE__ + 1
13
+ # Code taken from
14
+ # https://github.com/stevehodgkiss/sinatra-asset-pipeline/blob/master/app.rb#L11
15
+ set :sprockets, Sprockets::Environment.new(SERVER_PATH)
16
+ set :precompile, [ /\w+\.(?!js|css).+/, /application.(css|js)$/ ]
17
+ set :assets_prefix, 'assets'
18
+ set :assets_path, ::File.join(SERVER_PATH, 'public', assets_prefix)
19
+
20
+ configure do
21
+ # Lib
22
+ sprockets.append_path(::File.join(SERVER_PATH, 'lib', 'assets', 'stylesheets'))
23
+ sprockets.append_path(::File.join(SERVER_PATH, 'lib', 'assets', 'javascripts'))
24
+ sprockets.append_path(::File.join(SERVER_PATH, 'lib', 'assets', 'images'))
25
+
26
+ # Vendor
27
+ sprockets.append_path(::File.join(SERVER_PATH, 'vendor', 'assets', 'stylesheets'))
28
+ sprockets.append_path(::File.join(SERVER_PATH, 'vendor', 'assets', 'javascripts'))
29
+ sprockets.append_path(::File.join(SERVER_PATH, 'vendor', 'assets', 'images'))
30
+
31
+ # Assets
32
+ sprockets.append_path(::File.join(SERVER_PATH, 'assets', 'stylesheets'))
33
+ sprockets.append_path(::File.join(SERVER_PATH, 'assets', 'javascripts'))
34
+ sprockets.append_path(::File.join(SERVER_PATH, 'assets', 'images'))
35
+
36
+ sprockets.context_class.send :extend, Helpers::Asset
37
+ end
38
+ END
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,105 @@
1
+ require 'active_record'
2
+
3
+ module WatchTower
4
+ module Server
5
+ module Database
6
+ extend self
7
+
8
+ # Start the database server
9
+ #
10
+ # see #connect!
11
+ # see #migrate!
12
+ # @param [Hash] options
13
+ def start!(options = {})
14
+ LOG.debug("#{__FILE__}:#{__LINE__}: Starting the database server.")
15
+
16
+ # Connect to the Database
17
+ connect!
18
+
19
+ # Migrate the database
20
+ migrate!
21
+ rescue DatabaseConfigNotFoundError
22
+ STDERR.puts "Database configurations are missing, please edit #{Config::CONFIG_FILE} and try again."
23
+ exit(1)
24
+ rescue ::ActiveRecord::ConnectionNotEstablished => e
25
+ STDERR.puts "There was an error connecting to the database: #{e}"
26
+ exit(1)
27
+ end
28
+
29
+ # Stop the database server
30
+ #
31
+ # see #disconnect!
32
+ # @param [Hash] options
33
+ def stop!(options = {})
34
+ # Disconnect from the database
35
+ disconnect!
36
+ rescue DatabaseConfigNotFoundError
37
+ STDERR.puts "Database configurations are missing, please edit #{Config::CONFIG_FILE} and try again."
38
+ exit(1)
39
+ rescue ::ActiveRecord::ConnectionNotEstablished => e
40
+ STDERR.puts "There was an error connecting to the database: #{e}"
41
+ exit(1)
42
+ end
43
+
44
+ def is_connected?
45
+ ActiveRecord::Base.connected?
46
+ end
47
+
48
+ def is_migrated?
49
+ ActiveRecord::Migrator.current_version ==
50
+ ActiveRecord::Migrator.migrations(MIGRATIONS_PATH).last.version
51
+ end
52
+
53
+ protected
54
+ # Connect to the database
55
+ def connect!
56
+ return if is_connected?
57
+ LOG.debug("#{__FILE__}:#{__LINE__}: Connecting to the database.")
58
+ # Create a connection
59
+ ActiveRecord::Base.establish_connection(db_config)
60
+
61
+ # Create a looger
62
+ logger unless ENV['WATCH_TOWER_ENV'] == 'production'
63
+ end
64
+
65
+ # Disconnect from the database
66
+ # TODO: Implement this function
67
+ def disconnect!
68
+ raise NotImplementedError
69
+ end
70
+
71
+ # Migrate the database
72
+ def migrate!
73
+ return if is_migrated?
74
+ LOG.debug("#{__FILE__}:#{__LINE__}: Migrating the database.")
75
+ # Connect to the database
76
+ connect!
77
+
78
+ # Migrate the database
79
+ ActiveRecord::Migrator.migrate(MIGRATIONS_PATH)
80
+ end
81
+
82
+ # Get the database configuration
83
+ def db_config
84
+ db_config = Config.try(:[], :database).try(:[], ENV['WATCH_TOWER_ENV'])
85
+ raise DatabaseConfigNotFoundError unless db_config
86
+ if db_config[:adapter] =~ /sqlite/ && db_config[:database] != ":memory:"
87
+ db_config[:database] = ::File.expand_path(db_config[:database])
88
+ end
89
+ db_config
90
+ end
91
+
92
+ # Set the logger
93
+ def logger
94
+ ActiveRecord::Base.logger ||= Logger.new ::File.open(log_path, 'a')
95
+ end
96
+
97
+ # Get the log file's absolute path
98
+ #
99
+ # @return [String] The database log file depending on the environment
100
+ def log_path
101
+ ::File.join(LOG_PATH, "#{ENV['WATCH_TOWER_ENV']}_database.log")
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,15 @@
1
+ class CreateProjects < ActiveRecord::Migration
2
+ def change
3
+ create_table :projects do |t|
4
+ t.string :name, null: false
5
+ t.string :path, null: false
6
+ t.integer :elapsed_time, default: 0
7
+ t.integer :files_count
8
+
9
+ t.timestamps
10
+ end
11
+
12
+ add_index :projects, :name
13
+ add_index :projects, :path
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ class CreateFiles < ActiveRecord::Migration
2
+ def change
3
+ create_table :files do |t|
4
+ t.references :project, null: false
5
+ t.string :path, null: false
6
+ t.integer :elapsed_time, default: 0
7
+ t.integer :time_entries_count
8
+ t.integer :durations_count
9
+
10
+ t.timestamps
11
+ end
12
+
13
+ add_index :files, :project_id
14
+ add_index :files, :path, unique: true
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ class CreateTimeEntries < ActiveRecord::Migration
2
+ def change
3
+ create_table :time_entries do |t|
4
+ t.references :file, null: false
5
+ t.datetime :mtime, null: false
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :time_entries, :file_id
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ class CreateDurations < ActiveRecord::Migration
2
+ def change
3
+ create_table :durations do |t|
4
+ t.references :file, null: false
5
+ t.date :date, null: false
6
+ t.integer :duration, default: 0
7
+
8
+ t.timestamps
9
+ end
10
+
11
+ add_index :durations, :file_id
12
+ add_index :durations, :date
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ class AddHashToTimeEntries < ActiveRecord::Migration
2
+ def change
3
+ add_column :time_entries, :file_hash, :string, null: false, default: ""
4
+ add_index :time_entries, :file_hash
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ class AddHashToFiles < ActiveRecord::Migration
2
+ def change
3
+ add_column :files, :file_hash, :string, null: false, default: ""
4
+ add_index :files, :file_hash
5
+ end
6
+ end