potam 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.
- checksums.yaml +7 -0
- data/.rspec +1 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +52 -0
- data/README.rdoc +6 -0
- data/Rakefile +44 -0
- data/bin/potam +89 -0
- data/db/old.db +0 -0
- data/db/old2.db +0 -0
- data/db/potam.db +0 -0
- data/features/addnote.feature +26 -0
- data/features/addtask.feature +26 -0
- data/features/listtasks.feature +66 -0
- data/features/potam.feature +8 -0
- data/features/report.feature +58 -0
- data/features/step_definitions/potam_steps.rb +43 -0
- data/features/subtasks.feature +31 -0
- data/features/support/env.rb +27 -0
- data/features/taskinfo.feature +128 -0
- data/lib/db.rb +56 -0
- data/lib/dialog.rb +91 -0
- data/lib/notes.rb +3 -0
- data/lib/potam/version.rb +3 -0
- data/lib/potam.rb +9 -0
- data/lib/report.rb +48 -0
- data/lib/subtasks.rb +11 -0
- data/lib/tasks.rb +19 -0
- data/lib/timer.rb +12 -0
- data/potam.gemspec +23 -0
- data/potam.rdoc +5 -0
- data/results.html +480 -0
- data/spec/db_spec.rb +87 -0
- data/spec/notes_spec.rb +68 -0
- data/spec/report_spec.rb +89 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/subtasks_spec.rb +74 -0
- data/spec/tasks_spec.rb +86 -0
- data/spec/timer_spec.rb +31 -0
- data/test/clean.db +0 -0
- data/test/default_test.rb +14 -0
- data/test/test.db +0 -0
- data/test/test_helper.rb +9 -0
- metadata +148 -0
data/lib/db.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'timer'
|
2
|
+
|
3
|
+
class DB
|
4
|
+
|
5
|
+
include Timer
|
6
|
+
|
7
|
+
@@logged = true
|
8
|
+
|
9
|
+
def initialize(db = Sequel.sqlite("#{File.expand_path(File.dirname(__FILE__))}/../db/potam.db"))
|
10
|
+
@db = db
|
11
|
+
table_name = self.class.name.downcase
|
12
|
+
@record_name = table_name[0..-2]
|
13
|
+
self.class.__send__(:attr_reader, "new_#{@record_name}_id")
|
14
|
+
# @db = db
|
15
|
+
# instance_variable_set('@table', db[:"#{table_name}"])
|
16
|
+
@table = @db[:"#{table_name}"]
|
17
|
+
# Sequel.sqlite("#{File.expand_path(File.dirname(__FILE__))}/../test/test.db")
|
18
|
+
# @db = db
|
19
|
+
# @tasks = @db[:tasks]
|
20
|
+
end
|
21
|
+
|
22
|
+
def create(record)
|
23
|
+
record[:created_at] = now if @@logged
|
24
|
+
instance_variable_set("@new_#{@record_name}_id", @table.insert(record))
|
25
|
+
end
|
26
|
+
|
27
|
+
# def create(options = {})
|
28
|
+
# options.each do |key, value|
|
29
|
+
# instance_variable_set("@#{key}", value)
|
30
|
+
# end
|
31
|
+
# @new_task_id = @tasks.insert(title: @title, description: @description, created_at: @created_at)
|
32
|
+
# end
|
33
|
+
|
34
|
+
def last(task_id = false)
|
35
|
+
select_by_task_id(task_id).order(Sequel.desc(:id)).limit(10).all
|
36
|
+
end
|
37
|
+
|
38
|
+
def list(task_id = false)
|
39
|
+
select_by_task_id(task_id).order(Sequel.desc(:id)).all
|
40
|
+
end
|
41
|
+
|
42
|
+
def info(id)
|
43
|
+
@table.where("id = ?", id.to_i).first
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def select_by_task_id(task_id)
|
49
|
+
task_id ? @table.where("task_id = ?", task_id.to_i) : @table
|
50
|
+
end
|
51
|
+
|
52
|
+
# def time
|
53
|
+
# time = ENV['POTAM'] == 'test' ? ENV['POTAMTIME'].to_i : Time.now.to_i
|
54
|
+
# end
|
55
|
+
|
56
|
+
end
|
data/lib/dialog.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'highline/import'
|
2
|
+
require 'unicode'
|
3
|
+
|
4
|
+
module Dialog
|
5
|
+
|
6
|
+
attr_reader :new_task_title, :new_task_description, :new_note_text, :new_subtask_title
|
7
|
+
|
8
|
+
TRANSLATION = {
|
9
|
+
task: 'задача',
|
10
|
+
subtask: 'подзадача',
|
11
|
+
note: 'заметка',
|
12
|
+
created: 'создана',
|
13
|
+
finished: 'завершена'
|
14
|
+
}
|
15
|
+
|
16
|
+
WEEK = [nil, 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс']
|
17
|
+
|
18
|
+
def self.ask_new_task
|
19
|
+
@new_task_title = ask('Введите имя задачи: ')
|
20
|
+
@new_task_description = ask('Введите описание задачи: ')
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.ask_new_subtask
|
24
|
+
@new_subtask_title = ask('Введите подзадачу: ')
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.ask_new_note
|
28
|
+
@new_note_text = ask('Введите текст заметки: ')
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.say_tasks(tasks, indentation = '')
|
32
|
+
tasks.each do |task|
|
33
|
+
id = spaces("##{task[:id]}", 8)
|
34
|
+
title = spaces(task[:title], 41)
|
35
|
+
created_at = ts_to_date(task[:created_at])
|
36
|
+
say("#{indentation}#{id}#{title}#{created_at}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.say_task(task: task, subtasks: subtasks, notes: notes)
|
41
|
+
say("##{task[:id]} \"#{task[:title]}\"")
|
42
|
+
say(ts_to_date(task[:created_at]))
|
43
|
+
say(task[:description])
|
44
|
+
if subtasks[0]
|
45
|
+
say('Подзадачи:')
|
46
|
+
subtasks.each do |subtask|
|
47
|
+
created_at = ts_to_date(subtask[:created_at])
|
48
|
+
say(" #{created_at} #{subtask[:title]} (##{subtask[:id]})")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
if notes[0]
|
52
|
+
notes.each do |note|
|
53
|
+
say("\n#{ts_to_date(note[:created_at])}")
|
54
|
+
say(note[:text])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.say_report(report)
|
60
|
+
say('Проведена работа по следующим задачам:')
|
61
|
+
self.say_tasks(report[:tasks], ' ')
|
62
|
+
say('=' * 27)
|
63
|
+
report[:tasks].each do |task|
|
64
|
+
say(task[:title] + ':')
|
65
|
+
separator = false
|
66
|
+
report[:events].select{ |event| event[:task_id] == task[:id] }.each do |event|
|
67
|
+
say("\n") if separator
|
68
|
+
separator = true
|
69
|
+
wd = WEEK[ts_to_date(event[:timestamp], "%u").to_i]
|
70
|
+
say(' ' + ts_to_date(event[:timestamp], "%Y-%m-%d (#{wd}) %H:%M:%S"))
|
71
|
+
status = Unicode::capitalize(TRANSLATION[event[:status]])
|
72
|
+
object = TRANSLATION[event[:object]]
|
73
|
+
text = "\"#{event[:text]}\""
|
74
|
+
say(" #{status} #{object} #{text}")
|
75
|
+
end
|
76
|
+
say('-' * 27)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def spaces(text, width)
|
83
|
+
spaces = ' ' * (width - text.length)
|
84
|
+
return "#{text}#{spaces}"
|
85
|
+
end
|
86
|
+
|
87
|
+
def ts_to_date(timestamp, template = "%Y-%m-%d")
|
88
|
+
Time.at(timestamp.to_i).strftime(template)
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
data/lib/notes.rb
ADDED
data/lib/potam.rb
ADDED
data/lib/report.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'timer'
|
2
|
+
|
3
|
+
class Report
|
4
|
+
|
5
|
+
include Timer
|
6
|
+
|
7
|
+
def initialize(db = Sequel.sqlite("#{File.expand_path(File.dirname(__FILE__))}/../db/potam.db"))
|
8
|
+
@db = db
|
9
|
+
@report = Hash.new
|
10
|
+
@report[:events] = Array.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def week
|
14
|
+
@report[:tasks] = @db.fetch("SELECT * FROM tasks
|
15
|
+
WHERE (created_at BETWEEN #{last_mon} AND #{now})
|
16
|
+
OR id IN (SELECT task_id FROM subtasks WHERE (created_at BETWEEN #{last_mon} AND #{now})
|
17
|
+
OR (finished_at BETWEEN #{last_mon} AND #{now}))
|
18
|
+
OR id IN (SELECT task_id FROM notes WHERE (created_at BETWEEN #{last_mon} AND #{now}))
|
19
|
+
ORDER BY id DESC").to_a
|
20
|
+
order = Array.new
|
21
|
+
@report[:tasks].each{ |task| order << task[:id] }
|
22
|
+
@report[:tasks].select{ |task| task[:created_at].between?(last_mon, now) }.each{ |task| to_event(task) }
|
23
|
+
@db[:notes].where("created_at BETWEEN #{last_mon} AND #{now}").all.each{ |note| to_event(note) }
|
24
|
+
@db[:subtasks].where("created_at BETWEEN #{last_mon} AND #{now}").all.each{ |subtask| to_event(subtask) }
|
25
|
+
@db[:subtasks].where("finished_at BETWEEN #{last_mon} AND #{now}").all.each{ |subtask| to_event(subtask, :finished) }
|
26
|
+
@report[:events].sort_by!{ |event| [order.index(event[:task_id]), event[:timestamp]] }
|
27
|
+
return @report
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def to_event(object, status = :created)
|
33
|
+
if object[:description]
|
34
|
+
@report[:events] <<
|
35
|
+
{object: :task, status: :created, task_id: object[:id],
|
36
|
+
text: object[:title], timestamp: object[:created_at]}
|
37
|
+
elsif object[:text]
|
38
|
+
@report[:events] <<
|
39
|
+
{object: :note, status: :created, task_id: object[:task_id],
|
40
|
+
text: object[:text], timestamp: object[:created_at]}
|
41
|
+
else
|
42
|
+
@report[:events] <<
|
43
|
+
{object: :subtask, status: status, task_id: object[:task_id],
|
44
|
+
text: object[:title], timestamp: object[:"#{status}_at"]}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/lib/subtasks.rb
ADDED
data/lib/tasks.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class Tasks < DB
|
2
|
+
|
3
|
+
def last
|
4
|
+
@db.fetch("SELECT * FROM tasks AS T ORDER BY (SELECT MAX(ts) FROM
|
5
|
+
(SELECT notes.created_at AS ts FROM notes WHERE task_id = T.id
|
6
|
+
UNION SELECT subtasks.created_at AS ts FROM subtasks WHERE task_id = T.id
|
7
|
+
UNION SELECT subtasks.finished_at AS ts FROM subtasks WHERE task_id = T.id
|
8
|
+
UNION SELECT tasks.created_at AS ts FROM tasks WHERE id = T.id)) DESC LIMIT 0, 10;").to_a
|
9
|
+
end
|
10
|
+
|
11
|
+
def list
|
12
|
+
@db.fetch("SELECT * FROM tasks AS T ORDER BY (SELECT MAX(ts) FROM
|
13
|
+
(SELECT notes.created_at AS ts FROM notes WHERE task_id = T.id
|
14
|
+
UNION SELECT subtasks.created_at AS ts FROM subtasks WHERE task_id = T.id
|
15
|
+
UNION SELECT subtasks.finished_at AS ts FROM subtasks WHERE task_id = T.id
|
16
|
+
UNION SELECT tasks.created_at AS ts FROM tasks WHERE id = T.id)) DESC;").to_a
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/lib/timer.rb
ADDED
data/potam.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Ensure we require the local version and not one we might have installed already
|
2
|
+
require File.join([File.dirname(__FILE__),'lib','potam','version.rb'])
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
|
+
s.name = 'potam'
|
5
|
+
s.version = Potam::VERSION
|
6
|
+
s.author = 'Michael'
|
7
|
+
s.email = '0x22aa2@gmail.com'
|
8
|
+
# s.homepage = 'http://your.website.com'
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.summary = 'Personal Offline TAsk Manager - POTAM'
|
11
|
+
s.files = `git ls-files`.split("
|
12
|
+
")
|
13
|
+
s.require_paths << 'lib'
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.extra_rdoc_files = ['README.rdoc','potam.rdoc']
|
16
|
+
s.rdoc_options << '--title' << 'potam' << '--main' << 'README.rdoc' << '-ri'
|
17
|
+
s.bindir = 'bin'
|
18
|
+
s.executables << 'potam'
|
19
|
+
s.add_development_dependency('rake')
|
20
|
+
s.add_development_dependency('rdoc')
|
21
|
+
s.add_development_dependency('aruba')
|
22
|
+
s.add_runtime_dependency('gli','2.12.2')
|
23
|
+
end
|