watch_tower 0.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.
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