timekeeper 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 atog
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,18 @@
1
+ = timekeeper
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but
13
+ bump version in a commit by itself I can ignore when I pull)
14
+ * Send me a pull request. Bonus points for topic branches.
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2009 atog. See LICENSE for details.
data/bin/tk ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+ # == Synopsis
3
+ #
4
+ # Timekeeper. Keeping track of your time.
5
+ #
6
+ # == Usage
7
+ #
8
+ # tk [OPTIONS]
9
+ #
10
+ # -h, --help:
11
+ # show help
12
+ #
13
+ # --config [file]
14
+ # Location of your configuration file
15
+ #
16
+ # --title [title], -t [title]:
17
+ # What do you want to register
18
+ #
19
+ # --target [target], -c [target]:
20
+ # Who is going to pay?
21
+ #
22
+ # --time [time], -s [time]:
23
+ # How long did it take?
24
+ #
25
+ # --description [description], -m [description]
26
+ # More? You want to be more specific?
27
+ #
28
+ # --date [date], -d [date]
29
+ # When exactly did it happen?
30
+ #
31
+ # --remove [id]
32
+ # Remove a record.
33
+ #
34
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/timekeeper")
35
+
36
+ require "getoptlong"
37
+ require "rdoc/usage"
38
+
39
+ opts = GetoptLong.new(
40
+ [ "--help", "-h", GetoptLong::NO_ARGUMENT ],
41
+ [ "--title", "-t", GetoptLong::REQUIRED_ARGUMENT ],
42
+ [ "--target", "-c", GetoptLong::REQUIRED_ARGUMENT ],
43
+ [ "--time", "-s", GetoptLong::REQUIRED_ARGUMENT ],
44
+ [ "--description","-m", GetoptLong::REQUIRED_ARGUMENT ],
45
+ [ "--date", "-d", GetoptLong::REQUIRED_ARGUMENT ],
46
+ [ "--remove" , GetoptLong::REQUIRED_ARGUMENT ],
47
+ [ "--config" , GetoptLong::REQUIRED_ARGUMENT ]
48
+ )
49
+
50
+ if ARGV.length == 0
51
+ puts "Please provide some options, type --help"
52
+ exit 0
53
+ end
54
+
55
+ tk = Timekeeper.new
56
+
57
+ attributes = {}
58
+ opts.each do |opt, arg|
59
+ case opt
60
+ when "--help": RDoc::usage
61
+ when "--config": tk.config arg
62
+ when "--remove": tk.delete(arg); exit 0
63
+ else
64
+ attributes.store(opt.gsub("-",""), arg)
65
+ end
66
+ end
67
+
68
+ tk.store(attributes)
data/bin/tv ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+ # == Synopsis
3
+ #
4
+ # Timeviewer. Keeping an eye on your tracked time.
5
+ #
6
+ # == Usage
7
+ #
8
+ # tv [OPTIONS]
9
+ #
10
+ # -h, --help:
11
+ # show help
12
+ #
13
+ # --config [file]
14
+ # Location of your configuration file
15
+ #
16
+ # --name [name], -n [name]:
17
+ # Query by name
18
+ #
19
+ # --title [title], -t [title]:
20
+ # Query by title
21
+ #
22
+ # --target [target], -c [target]:
23
+ # Query by target
24
+ #
25
+ # --description [description], -m [description]
26
+ # Query by description
27
+ #
28
+ # --date [date], -d [date]
29
+ # Query by date
30
+ #
31
+ require File.dirname(__FILE__) + '/../lib/timekeeper'
32
+
33
+ require "getoptlong"
34
+ require "rdoc/usage"
35
+ require "fastercsv"
36
+
37
+ opts = GetoptLong.new(
38
+ [ "--help", "-h", GetoptLong::NO_ARGUMENT ],
39
+ [ "--csv" , GetoptLong::NO_ARGUMENT ],
40
+ [ "--all" , GetoptLong::NO_ARGUMENT ],
41
+ [ "--name", "-n", GetoptLong::REQUIRED_ARGUMENT ],
42
+ [ "--title", "-t", GetoptLong::REQUIRED_ARGUMENT ],
43
+ [ "--target", "-c", GetoptLong::REQUIRED_ARGUMENT ],
44
+ [ "--time", "-s", GetoptLong::REQUIRED_ARGUMENT ],
45
+ [ "--description","-m", GetoptLong::REQUIRED_ARGUMENT ],
46
+ [ "--date", "-d", GetoptLong::REQUIRED_ARGUMENT ],
47
+ [ "--config" , GetoptLong::REQUIRED_ARGUMENT ]
48
+ )
49
+
50
+ if ARGV.length == 0
51
+ puts "Please provide some options, type --help"
52
+ exit 0
53
+ end
54
+
55
+ tv = Timeviewer.new
56
+ output = nil
57
+
58
+ attributes = {}
59
+ opts.each do |opt, arg|
60
+ case opt
61
+ when "--help": RDoc::usage
62
+ when "--csv" : output = :csv
63
+ when "--config": tv.config arg
64
+ else
65
+ attributes.store(opt.gsub("-",""), arg)
66
+ end
67
+ end
68
+
69
+ records = tv.all
70
+ if output
71
+ Timeviewer.export(records, "export", output)
72
+ else
73
+ puts records.collect{|r| Keep.new(r) }
74
+ end
data/lib/timekeeper.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "rubygems"
2
+ require "rufus/tokyo"
3
+
4
+ require File.dirname(__FILE__) + "/timekeeper/keep"
5
+ require File.dirname(__FILE__) + "/timekeeper/timekeeper"
6
+ require File.dirname(__FILE__) + "/timekeeper/timeviewer"
@@ -0,0 +1,72 @@
1
+ class Keep
2
+ YES = ["YES", "Y", "y", "yes", "true", true]
3
+ NO = ["NO", "N", "n", "no", "false", false, nil]
4
+
5
+ attr_accessor :name, :time, :title, :description, :target, :date, :pk, :track
6
+
7
+ def initialize(attributes)
8
+ set_attributes(attributes)
9
+ end
10
+
11
+ def update(attributes)
12
+ set_attributes(attributes)
13
+ end
14
+
15
+ def date=(value)
16
+ if value
17
+ if value.is_a?(Date)
18
+ @date = value
19
+ else
20
+ @date = parse_date(value.to_s)
21
+ end
22
+ end
23
+ end
24
+
25
+ def track=(value)
26
+ if YES.include?(value)
27
+ @track = true
28
+ elsif NO.include?(value)
29
+ @track = false
30
+ end
31
+ end
32
+
33
+ def validate
34
+ mandatory(%w(name target title date time))
35
+ end
36
+
37
+ def to_hash
38
+ {:name => name, :time => time, :title => title, :description => description,
39
+ :target => target, :date => date, :track => track}
40
+ end
41
+
42
+ def to_s
43
+ "#{pk}|#{name}|#{target}|#{title}|#{description}|#{date}|#{time}|#{track}"
44
+ end
45
+
46
+ private
47
+
48
+ def set_attributes(attributes)
49
+ attributes.each do |key, value|
50
+ respond_to?("#{key}=") ? send("#{key}=", value) : raise(StandardError, "unknown attribute: #{key}")
51
+ end
52
+ validate
53
+ self
54
+ end
55
+
56
+ def parse_date(value)
57
+ case value
58
+ when "today" : Date.today
59
+ when "yesterday": Date.today - 1
60
+ when "tomorrow" : Date.today + 1
61
+ else
62
+ Date.parse(value)
63
+ end
64
+ end
65
+
66
+ def mandatory(attributes)
67
+ attributes.each do |attribute|
68
+ raise(StandardError, "#{attribute} is mandatory") unless send(attribute)
69
+ end
70
+ end
71
+
72
+ end
@@ -0,0 +1,37 @@
1
+ class Timekeeper
2
+
3
+ def config(file="timekeeper.yml")
4
+ @config ||= YAML.load_file(file)
5
+ end
6
+
7
+ def delete(id)
8
+ table.delete(id)
9
+ end
10
+
11
+ def delete_all
12
+ table.clear
13
+ end
14
+
15
+ def store(attributes)
16
+ attributes.store("name", config["name"])
17
+ attributes.store("date", Date.today) unless attributes["date"]
18
+ table[table.genuid] = Keep.new(attributes).to_hash
19
+ end
20
+
21
+ def get(id)
22
+ if attributes = table.lget(id.to_s).values.first
23
+ Keep.new(attributes)
24
+ end
25
+ end
26
+
27
+ def update(id, attributes_to_update)
28
+ if attributes = table.lget(id.to_s).values.first
29
+ table[id] = Keep.new(attributes).update(attributes_to_update).to_hash
30
+ end
31
+ end
32
+
33
+ def table
34
+ @table ||= Rufus::Tokyo::Table.new(File.join(config["db_path"],"#{config["name"]}-time.tct"))
35
+ end
36
+
37
+ end
@@ -0,0 +1,31 @@
1
+ class Timeviewer
2
+
3
+ def config(file="timekeeper.yml")
4
+ @config ||= YAML.load_file(file)
5
+ end
6
+
7
+ def all
8
+ tables.collect{|table| table.query}.flatten!
9
+ end
10
+
11
+ def self.export(records, name="export", type= :csv)
12
+ if records.any?
13
+ case type
14
+ when :csv
15
+ FasterCSV.open("#{name}.#{type}", "w") do |csv|
16
+ csv << records[0].keys
17
+ records.each do |record|
18
+ csv << record.values
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def tables
28
+ @tables ||= config["team"].collect{|t| Rufus::Tokyo::Table.new(File.join(config["db_path"],"#{t}-time.tct"))}
29
+ end
30
+
31
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: timekeeper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - atog
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-01 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: fastercsv
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.5.0
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: rufus-tokyo
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.0
44
+ version:
45
+ description: Timekeeper. Keeping track of your time.
46
+ email: koen@atog.be
47
+ executables:
48
+ - tk
49
+ - tv
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - LICENSE
54
+ - README.rdoc
55
+ files:
56
+ - lib/timekeeper.rb
57
+ - lib/timekeeper/keep.rb
58
+ - lib/timekeeper/timekeeper.rb
59
+ - lib/timekeeper/timeviewer.rb
60
+ - LICENSE
61
+ - README.rdoc
62
+ has_rdoc: true
63
+ homepage: http://github.com/atog/timekeeper
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options:
68
+ - --charset=UTF-8
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: "0"
82
+ version:
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.5
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Timekeeper. Keeping track of your time.
90
+ test_files: []
91
+