dev_flow 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/dw CHANGED
@@ -26,6 +26,7 @@ optparse = OptionParser.new do |opts|
26
26
  opts.separator " close : close the task as a leader"
27
27
  opts.separator " release : close a release task"
28
28
  opts.separator " clean[up] : delete local branches that already completed"
29
+ opts.separator " gantt : create gantt chart html files under docs folder"
29
30
  opts.separator ""
30
31
  opts.separator "Options:"
31
32
 
@@ -50,6 +51,11 @@ optparse = OptionParser.new do |opts|
50
51
  options[:offline] = true
51
52
  end
52
53
 
54
+ options[:docs] = 'docs'
55
+ opts.on('-d DIR', '--docs DIR', 'document directory for gantt chart') do |dir|
56
+ options[:docs] = dir
57
+ end
58
+
53
59
  opts.on('-v', '--verbose', 'print more messages') do
54
60
  options[:verbose] = true
55
61
  end
@@ -67,7 +73,7 @@ command = ARGV[0] || 'info'
67
73
  cmd_alias = {'pg' => 'progress', 'update-roadmap' => 'ur', 'clean' => 'cleanup', 's' => 'switch'}
68
74
  command = cmd_alias[command] if cmd_alias[command]
69
75
 
70
- if %w[info init complete progress close release ur update-roadmap cleanup clean switch].include? command
76
+ if %w[info init complete progress close release ur update-roadmap cleanup clean switch gantt].include? command
71
77
  options[:command] = command
72
78
  else
73
79
  puts "Unknown command #{command}".red
data/lib/dev_flow/app.rb CHANGED
@@ -27,9 +27,7 @@ module DevFlow
27
27
  info "Load local configuration from #{@config[:local_config]}"
28
28
  @config = @config.merge(YAML.load(File.open(@config[:local_config], 'r:utf-8').read))
29
29
  end
30
-
31
- error "Do not work on master branch. Please swith to develop branch." if @git.current_branch == 'master'
32
-
30
+
33
31
  # load roadmap into variable @roadmap
34
32
  load_roadmap
35
33
 
File without changes
@@ -0,0 +1,51 @@
1
+ require 'fileutils'
2
+ require 'erubis'
3
+
4
+ module DevFlow
5
+ class Gantt < App
6
+
7
+ ## fetch git log
8
+ def git_log
9
+ git_log = ''
10
+ committer = ''
11
+ last_header = ''
12
+ `git log --graph --format=email --date=relative -n 50`.split(/\n/).each do |line|
13
+ # {{{
14
+ line.chomp!
15
+ line.gsub!(">", "&gt;")
16
+ line.gsub!("<", "&lt;")
17
+ if /^(?<header_>\W+)From\s+(?<hash_code_>\w+)/ =~ line
18
+ git_log += "#{header_}<em style='color:grey'>#{hash_code_}</em>\n"
19
+ elsif /^(?<header_>\W+)From\:\s+(?<committer_>.+)$/ =~ line
20
+ committer = committer_
21
+ last_header = header_
22
+ elsif /^(?<header_>\W+)Date\:\s*(?<date_>.+)$/ =~ line
23
+ git_log += sprintf("%s<strong>%s</strong> By %s\n", last_header, DateTime.parse(date_).strftime("%F %R"), committer)
24
+ git_log += header_
25
+ elsif /^(?<header_>\W+)Subject\:\s+\[PATCH\]\s*(?<message_>.+)$/ =~ line
26
+ color = 'green'
27
+ git_log += "#{header_}<strong style='color:#{color}'>#{message_}</strong>\n"
28
+ else
29
+ git_log += line + "\n"
30
+ end
31
+ end
32
+ git_log
33
+ end
34
+
35
+ ## create gantt chart from templates
36
+ def process!
37
+ docs = @config[:docs]
38
+ html_file = "#{docs}/gantt.html"
39
+ FileUtils.mkdir_p "#{docs}" unless File.directory? "#{docs}"
40
+
41
+ tpl_dir = File.expand_path(File.dirname(__FILE__) + "/../../../templates")
42
+ FileUtils.cp_r "#{tpl_dir}/css", docs
43
+ FileUtils.cp_r "#{tpl_dir}/js", docs
44
+
45
+ wfh = File.open(html_file, "w:utf-8")
46
+ wfh.puts Erubis::Eruby.new(File.read("#{tpl_dir}/jsgantt.html.erb")).result(:rm => @roadmap, :is_roadmap => true, :git_log => git_log, :resource => nil)
47
+ wfh.close
48
+ end
49
+
50
+ end
51
+ end
@@ -19,7 +19,7 @@ module DevFlow
19
19
  end
20
20
 
21
21
  def title
22
- @config[:title]
22
+ @config["title"]
23
23
  end
24
24
 
25
25
  def team_member_names
@@ -0,0 +1,71 @@
1
+ module DevFlow
2
+
3
+ class Task
4
+
5
+ def task_id
6
+ self.ln
7
+ end
8
+
9
+ def parent_id
10
+ self.parent ? self.parent.task_id : 0
11
+ end
12
+
13
+ def resource_name
14
+ self.resource_names.join ","
15
+ end
16
+
17
+ def dependencies_str
18
+ self.dependencies.map {|d| d.task_id}.join ","
19
+ end
20
+
21
+ ## color reflects the status of a task, return a hex code without heading "#"
22
+ def color resource_ = nil
23
+ today = DateTime.now.strftime("%Y%m%d").to_i
24
+ start_day = self.start_date.strftime("%Y%m%d").to_i
25
+ end_day = self.end_date.strftime("%Y%m%d").to_i
26
+ hex = "B0C4DE" # light steel blue as default
27
+ hex = "808080" unless self.is_workable? # grey for no able to start
28
+ hex = "FFD700" if start_day == today and progress == 0 # gold for must start now
29
+ hex = "FFFF00" if self.progress > 0 and self.progress < 100 # blue for working
30
+ hex = "FFA500" if end_day == today and self.progress < 100 # orange for master complete today
31
+
32
+ if resource_
33
+ hex = "CCCCCC" unless self.resources.include? resource_
34
+ end
35
+
36
+ hex = "008000" if self.is_completed? # green for completed
37
+ hex = "FF0000" if self.progress < 100 and today > end_day # red for not completed on time
38
+ hex = "FF0000" if self.progress == 0 and today > start_day # red for late start
39
+ hex = "EEE8AA" if self.is_deleted?
40
+ hex = "C0C0C0" if self.is_pending?
41
+ # puts hex + ":" + self.progress.to_s + ";" + DateTime.now.strftime("%Y%m%d") + ":" + self.start_date.strftime("%Y%m%d")
42
+ hex
43
+ end
44
+
45
+ def caption
46
+ return "" if self.children.size > 0
47
+ cap = self.resource_name
48
+ cap = sprintf("Pending (%s)", cap) if self.is_pending?
49
+ cap = sprintf("Deleted (%s)", cap) if self.is_deleted?
50
+ if self.is_completed?
51
+ cap += self.completed_at.strftime("%F")
52
+ else
53
+ cap += sprintf(':%02d\%', self.progress) if self.progress > 0
54
+ end
55
+ cap
56
+ end
57
+
58
+ def as_js resource
59
+ is_milestone_flag = self.is_milestone? ? 1 : 0
60
+ is_parent_flag = self.is_parent? ? 1 : 0
61
+ task_str = " g.AddTaskItem(new JSGantt.TaskItem(%d,'%s','%s','%s','%s','%s',%d,'%s',%d,%d,%d,%d,'%s','%s'));\n"
62
+ sprintf(task_str, self.task_id, self.display_name,
63
+ self.start_date.strftime("%m/%d/%Y"),
64
+ self.end_date.strftime("%m/%d/%Y"),
65
+ self.color(resource), '', is_milestone_flag,
66
+ self.resource_name, self.progress.to_i, is_parent_flag,
67
+ self.parent_id, 1, self.dependencies_str, self.caption)
68
+ end
69
+ end
70
+
71
+ end
@@ -1,3 +1,3 @@
1
1
  module DevFlow
2
- VERSION = '0.3.1'
2
+ VERSION = '0.4.0'
3
3
  end
data/lib/dev_flow.rb CHANGED
@@ -9,6 +9,7 @@ require 'dev_flow/member'
9
9
 
10
10
  # presenter
11
11
  require 'dev_flow/task_console'
12
+ require 'dev_flow/task_js'
12
13
 
13
14
  # application and commands
14
15
  require 'dev_flow/app'
data/tags CHANGED
File without changes
@@ -0,0 +1,53 @@
1
+
2
+ // These are the class/styles used by various objects in GanttChart. However, Firefox has problems deciphering class style when DIVs are embedded in other DIVs.
3
+
4
+ // GanttChart makes heavy use of embedded DIVS, thus the style are often embedded directly in the objects html. If this could be resolved with Firefox, it would
5
+
6
+ // make alot of the code look simpleer/cleaner without all the embedded styles
7
+
8
+
9
+
10
+ ..gantt { font-family:tahoma, arial, verdana; font-size:10px;}
11
+
12
+ ..gdatehead { BORDER-TOP: #efefef 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #efefef 1px solid; HEIGHT: 18px }
13
+
14
+ ..ghead { BORDER-TOP: #efefef 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #efefef 1px solid; WIDTH: 24px; HEIGHT: 20px }
15
+
16
+ ..gname { BORDER-TOP: #efefef 1px solid; FONT-SIZE: 12px; WIDTH: 18px; HEIGHT: 18px }
17
+
18
+ ..ghead A { FONT-SIZE: 10px; COLOR: #000000; TEXT-DECORATION: none }
19
+
20
+ ..gheadwkend A { FONT-SIZE: 10px; COLOR: #000000; TEXT-DECORATION: none }
21
+
22
+ ..gheadwkend { BORDER-TOP: #efefef 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #efefef 1px solid; WIDTH: 24px; HEIGHT: 20px; background-color: #cfcfcf }
23
+
24
+ ..gfiller { BORDER-TOP: #efefef 1px solid; BORDER-LEFT: #efefef 1px solid; WIDTH: 18px; HEIGHT: 18px }
25
+
26
+ ..gfillerwkend { BORDER-LEFT: #efefef 1px solid; WIDTH: 18px; HEIGHT: 18px; BACKGROUND-COLOR: #cfcfcf }
27
+
28
+ ..gitem { BORDER-TOP: #cccccc 1px solid; WIDTH: 18px; HEIGHT: 18px }
29
+
30
+ ..gitemwkend { BORDER-TOP: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; WIDTH: 18px; HEIGHT: 18px }
31
+
32
+ ..gmilestone { BORDER-TOP: #efefef 1px solid; FONT-SIZE: 14px; OVERFLOW: hidden; BORDER-LEFT: #efefef 1px solid; WIDTH: 18px; HEIGHT: 18px}
33
+
34
+ ..gmilestonewkend { BORDER-TOP: #efefef 1px solid; BORDER-LEFT: #cccccc 1px solid; WIDTH: 18px; HEIGHT: 18px}
35
+
36
+ ..btn { BORDER-RIGHT: #ffffff; BORDER-TOP: #ffffff; FONT-WEIGHT: bold; FONT-SIZE: 10px; BORDER-LEFT: #ffffff; WIDTH: 12px; COLOR: #cccccc; BORDER-BOTTOM: #ffffff; BACKGROUND-COLOR: #ffffff }
37
+
38
+ ..hrcomplete { BORDER-RIGHT: #000000 2px solid; PADDING-RIGHT: 0px; BORDER-TOP: #000000 2px solid; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; BORDER-LEFT: #000000 2px solid; WIDTH: 20px; COLOR: #000000; PADDING-TOP: 0px; BORDER-BOTTOM: #000000 2px solid; HEIGHT: 4px }
39
+
40
+ ..hrhalfcomplete { BORDER-RIGHT: #000000 2px solid; BORDER-TOP: #000000 2px solid; BORDER-LEFT: #000000 2px solid; WIDTH: 9px; COLOR: #000000; BORDER-BOTTOM: #000000 2px solid; HEIGHT: 4px }
41
+
42
+ ..gweekend { font-family:tahoma, arial, verdana; font-size:11px; background-color:#EEEEEE; text-align:center; }
43
+
44
+ ..gtask { font-family:tahoma, arial, verdana; font-size:11px; background-color:#00FF00; text-align:center; }
45
+
46
+ ..gday { font-family:tahoma, arial, verdana; font-size:11px; text-align:center; }
47
+
48
+ ..gcomplete { background-color:black; height:5px; overflow: auto; margin-top:4px; }
49
+
50
+ DIV.scroll { BORDER-RIGHT: #efefef 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #efefef 1px solid; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; OVERFLOW: hidden; BORDER-LEFT: #efefef 1px solid; WIDTH: 420px; PADDING-TOP: 0px; BORDER-BOTTOM: #efefef 1px solid; BACKGROUND-COLOR: #ffffff }
51
+
52
+ DIV.scroll2 { position:relative; PADDING-RIGHT: 0px; overflow:auto ;overflow-x:scroll;overflow-y:hidden; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; WIDTH: 482px; PADDING-TOP: 0px; BACKGROUND-COLOR: #ffffff }
53
+