redmine_cli 0.5.1 → 0.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f495b25e5f3bcf3c39572f4217c898c2d6d31664
4
- data.tar.gz: 8677006b2a6184346b9554d0f73b1c9037824716
3
+ metadata.gz: 2479d08810ffc54eb4bbdfb57148a88da022f257
4
+ data.tar.gz: deded6244bc061858921682443d02a95ed089298
5
5
  SHA512:
6
- metadata.gz: 92f258a59b5f0a66b3579b5ff299528ce06a0bd4d8cdd5e97132251e4b1660346c084f2b19b1910ef26ea314d6565c16ede635b1de75258508e444b4a2defcad
7
- data.tar.gz: 7b549586215ad72aa4b06242b9fe703b3b54d4ce0c45edd1bf0a21db43c8430168a68f132a8f5a61a2424c8e5f0fe3d4cd4c5713e2a9bdd0b23c56c3d7f10ece
6
+ metadata.gz: 5ef74fd825bd0db651b61b17f4b949d482d4476feebaf42ec62d7c4675de5316a3882b30320896556f1601f2d333e61f763881c28fe118d7e7edb8b41e24cd9c
7
+ data.tar.gz: 9b83f76f4ee0f9c852bd1b98393a387d250c99fdfdded638c080e9c5abde7c8baddda0ad19ed970ffd1826f9dfc1c69a52838b8e38df330de0d9314f8feea51b
data/.rvmrc CHANGED
@@ -1,9 +1,11 @@
1
+ echo 'rvm use 2.2.1@redmine_cli --create'
1
2
  rvm use 2.2.1@redmine_cli --create
3
+
2
4
  if [ -z "$(gem list | grep '^bundler\s')" ]; then
3
5
  echo
4
6
  echo '--- WARNING ---'
5
7
  echo 'I cannot find "bundler" gem.'
6
- echo 'Looks like you use gemset "profit-gis" at first time.'
8
+ echo 'Looks like you use gemset "redmine_cli" at first time.'
7
9
  echo 'Please, execute: gem install bundler; bundle install'
8
10
  echo
9
11
  fi
data/README.md CHANGED
@@ -3,7 +3,12 @@
3
3
 
4
4
  Command-Line Interface for Redmine.
5
5
 
6
- Why? 'cause web-browser + mouse sucks
6
+ Why? Because web-browser + mouse sucks
7
+
8
+ I hate using Redmine web-interface. All these mouse moves and clicks...
9
+ This CLI allows me to do some tasks much faster: I read issue descriptions and last comments right in the console.
10
+
11
+ It doesnt provide much functional so I need to open my browser sometimes, but for most of my tasks it fits well.
7
12
 
8
13
  ## Installation
9
14
 
@@ -29,6 +34,8 @@ Why? 'cause web-browser + mouse sucks
29
34
  Don't forget about console aliases!
30
35
  I use something like this:
31
36
 
37
+ # ~/.bashrc
38
+ #
32
39
  # alias i='redmine issue'
33
40
  # by the way, Thor can guess your commands so:
34
41
 
@@ -10,18 +10,23 @@ en:
10
10
  show: 'More info about issue'
11
11
  update: 'Change some issue params, add time entry, comment'
12
12
  create: 'Create issue'
13
+ complete: 'Sets readiness to 100, changes assignee, changes status'
13
14
  options:
14
15
  show:
15
16
  limit: 'Amount of comments (last journals).'
17
+ comments: 'Show only journals with comments'
16
18
  update:
17
19
  done: 'Readiness percentage'
18
- assign: 'ID of name part of user issue will be assigned to'
20
+ assign: 'ID or name part of user issue will be assigned to'
19
21
  time: 'Add time entry. Formats: HH:MM; M (minutes); H.h (hours in float)'
20
22
  status: 'Change status of issue. Search by status name substring'
21
23
  comment: 'Leave comment. It will open your text editor.'
22
24
  description: 'Change description with your text editor.'
25
+ complete:
26
+ assign: 'ID or name part of user issue will be assigned to. If not defined, issue will be assigned to its author.'
23
27
  conf:
24
28
  init: 'Asks you few question to make your config file useful'
29
+ status_complete: 'Sets default status for completed issues'
25
30
  user:
26
31
  find: 'Finds users by id|email|name. Without arguments it will show your info'
27
32
  project:
@@ -33,6 +38,8 @@ en:
33
38
  enter_user: 'Enter your login to Redmine: '
34
39
  enter_password: 'Enter your password: '
35
40
  enter_site: 'Enter URL to your Redmine: '
41
+ status_complete:
42
+ select_status: 'Please, select status for completed issues.'
36
43
  issue:
37
44
  update:
38
45
  type_comment_here: 'Type your comment here, save file and close'
@@ -52,4 +59,5 @@ en:
52
59
  select_item_from_list: 'Select item from list: '
53
60
  trackers: 'trackers'
54
61
  projects: 'projects'
55
-
62
+ versions: 'versions'
63
+ without_version: '<without version>'
@@ -1,13 +1,12 @@
1
-
2
1
  % ljust_value = 15
3
2
  % info = { 'ID' => issue.id,
4
3
  % 'Subject' => issue.subject,
5
4
  % 'Status' => issue.status.name,
6
5
  % 'Priority' => issue.priority.name,
7
6
  % 'Readiness' => issue.done_ratio + '%',
8
- % 'Author' => "#{issue.author.name} (#{issue.author.id})" }
7
+ % 'Author' => TemplateRenderer.render('issue/show/user', user: issue.author) }
9
8
  %
10
- % info['Assigned to'] = "#{issue.assigned_to.name} (#{issue.assigned_to.id})" if issue.assigned_to?
9
+ % info['Assigned to'] = TemplateRenderer.render('issue/show/user', user: issue.assigned_to) if issue.assigned_to?
11
10
  % info['Project'] = issue.project.name if issue.project?
12
11
  % info['Version'] = issue.fixed_version.name if issue.fixed_version?
13
12
  % info['Parent'] = "#{issue.parent.id} - #{issue.parent.reload.subject.cut(80)}" if issue.parent?
@@ -34,7 +33,7 @@
34
33
 
35
34
  % end
36
35
  %
37
- % if issue.attachments?
36
+ % if issue.attachments.size > 0
38
37
  <%= 'Attachments:'.yellow %>
39
38
 
40
39
  % issue.attachments.each do |a|
@@ -53,25 +52,8 @@
53
52
  % journals = []
54
53
  % issue.journals.reverse.each do |j|
55
54
  % break if journals.size > journals_limit
56
- % next unless j.notes?
55
+ % next if comments_only && !j.notes
57
56
  % journals.push j
58
57
  % end
59
-
60
- % journals.reverse.each do |j|
61
-
62
- <%= "----------\n".yellow %>
63
- % journal_info = { 'From' => "#{j.user.name} (#{j.user.id})",
64
- % 'Created' => j.created_on }
65
- %
66
- % journal_info.each do |k, v|
67
- <%= "#{k}:".ljust(ljust_value).yellow %> <%= v %>
68
-
69
- % end
70
-
71
-
72
- <%= j.notes %>
73
-
74
-
75
- % end
76
-
58
+ <%= TemplateRenderer.render 'issue/show/journals', journals: journals, ljust_value: ljust_value %>
77
59
  % end
@@ -0,0 +1,45 @@
1
+ % name = detail.name
2
+ % old_value = detail.old_value
3
+ % new_value = detail.new_value
4
+ %
5
+ % if detail.attribute?
6
+ % case name
7
+ % when 'subject', 'description'
8
+ % attribute = name.capitalize
9
+ % old = old_value.nil? ? '0' : old_value.size.to_s
10
+ % new = new_value.nil? ? '0' : new_value.size.to_s
11
+ %
12
+ % changes = "#{old_value ? old_value.size : 0} chars" + ' -> '.white + "#{new_value ? new_value.size : 0} chars"
13
+ % when 'assigned_to_id'
14
+ % attribute = 'Assigned'
15
+ % changes = TemplateRenderer.render('issue/show/detail/user', new_value: new_value, old_value: old_value)
16
+ % when 'done_ratio'
17
+ % attribute = 'Readiness'
18
+ % changes = "#{old_value}%" + ' -> '.white + "#{new_value}%"
19
+ % when 'estimated_hours'
20
+ % attribute = 'Estimated'
21
+ % changes = "#{old_value || 'nil'}" + ' -> '.white + "#{new_value || 'nil'}"
22
+ % when 'fixed_version_id'
23
+ % attribute = 'Version'
24
+ % changes = TemplateRenderer.render 'issue/show/detail/some_object',
25
+ % new_value: new_value,
26
+ % old_value: old_value,
27
+ % object_class: RedmineRest::Models::Version
28
+ % when 'status_id'
29
+ % attribute = 'Status'
30
+ % changes = TemplateRenderer.render 'issue/show/detail/status',
31
+ % new_value: new_value,
32
+ % old_value: old_value
33
+ % else
34
+ % attribute = name.capitalize
35
+ % changes = "#{old_value || 'nil'}" + ' -> '.white + "#{new_value || 'nil'}"
36
+ % end
37
+ %
38
+ % output = "#{attribute}:".ljust(ljust_value).white + changes
39
+ %
40
+ % elsif detail.relation?
41
+ % output = new_value.nil? ? "not #{name} #{old_value}" : "#{name} #{new_value}"
42
+ % else
43
+ % output = detail.inspect
44
+ % end
45
+ <%= output %>
@@ -0,0 +1,16 @@
1
+ % old_obj = object_class.find_by_id(old_value)
2
+ % old = if old_obj
3
+ % old_obj.name.to_s + "[#{old_obj.id}]".red
4
+ % else
5
+ % 'nil'
6
+ % end
7
+ %
8
+ % new_obj = object_class.find_by_id(new_value)
9
+ % new = if new_obj
10
+ % new_obj.name.to_s + "[#{new_obj.id}]".red
11
+ % else
12
+ % 'nil'
13
+ % end
14
+ %
15
+ % output = old + ' -> '.white + new
16
+ <%= output %>
@@ -0,0 +1,18 @@
1
+ % list = RedmineRest::Models::IssueStatus.all
2
+ %
3
+ % old_status = list.find { |i| i.id == old_value }
4
+ % old = if old_status
5
+ % old_status.name.to_s + "[#{old_status.id}]".red
6
+ % else
7
+ % 'nil'
8
+ % end
9
+ %
10
+ % new_status = list.find { |i| i.id == new_value }
11
+ % new = if new_status
12
+ % new_status.name.to_s + "[#{new_status.id}]".red
13
+ % else
14
+ % 'nil'
15
+ % end
16
+ %
17
+ % output = old + ' -> '.white + new
18
+ <%= output %>
@@ -0,0 +1,6 @@
1
+ % old = TemplateRenderer.render 'issue/show/user', user: old_value
2
+ % new = TemplateRenderer.render 'issue/show/user', user: new_value
3
+ %
4
+ % output = old + ' -> '.white + new
5
+ %
6
+ <%= output %>
@@ -0,0 +1,21 @@
1
+ % journals.reverse.each do |j|
2
+
3
+ <%= "----------\n".yellow %>
4
+ % journal_info = { 'From' => TemplateRenderer.render('issue/show/user', user: j.user),
5
+ % 'Created' => j.created_on }
6
+ %
7
+ % journal_info.each do |k, v|
8
+ <%= "#{k}:".ljust(ljust_value).yellow %> <%= v %>
9
+
10
+ % end
11
+
12
+ % if j.details
13
+ % j.details.each do |d|
14
+ * <%= TemplateRenderer.render 'issue/show/detail', detail: d, ljust_value: ljust_value %>
15
+ % end
16
+
17
+ % end
18
+ <%= j.notes %>
19
+
20
+
21
+ % end
@@ -0,0 +1,13 @@
1
+ % record = case user
2
+ % when String, Fixnum then RedmineRest::Models::User.find_by_id(user)
3
+ % when RedmineRest::Models::User then user
4
+ % else nil
5
+ % end
6
+ %
7
+ % output = if record
8
+ % (record.name? ? record.name : "#{record.firstname} #{record.lastname}") + "[#{record.id}]".red
9
+ % else
10
+ % 'nil'
11
+ % end
12
+ %
13
+ <%= output %>
@@ -14,6 +14,7 @@ module RedmineCLI
14
14
 
15
15
  def set_attributes
16
16
  set_project
17
+ set_version
17
18
  set_tracker
18
19
  set_subject
19
20
  set_description
@@ -26,10 +27,18 @@ module RedmineCLI
26
27
  @issue.project_id = @project.id
27
28
  end
28
29
 
30
+ def set_version
31
+ list = [dummy_object_with_name(m(:without_version))] + @project.versions.to_a
32
+ return if list.size == 1
33
+
34
+ puts Unicode.upcase(m(:versions)) + ':'
35
+ @version = ask_for_object(list)
36
+ @issue.fixed_version_id = @version.is_a?(Models::Version) ? @version.id : nil
37
+ end
38
+
29
39
  def set_tracker
30
40
  puts Unicode.upcase(m(:trackers)) + ':'
31
- # @issue.tracker_id = ask_for_object(@project.trackers).id
32
- @issue.tracker_id = ask_for_object(Models::Tracker.all)
41
+ @issue.tracker_id = ask_for_object(Models::Tracker.all).id
33
42
  end
34
43
 
35
44
  def set_subject
@@ -48,6 +57,13 @@ module RedmineCLI
48
57
  @assignee = ask_for_object(@project.members)
49
58
  @issue.assigned_to_id = @assignee.id
50
59
  end
60
+
61
+ def dummy_object_with_name(name)
62
+ dummy = Object.new
63
+ dummy.define_singleton_method(:name) { name }
64
+
65
+ dummy
66
+ end
51
67
  end
52
68
  end
53
69
  end
@@ -39,9 +39,16 @@ module RedmineCLI
39
39
  end
40
40
 
41
41
  def update_status(issue)
42
- return unless options[:status]
42
+ opt = options[:status]
43
+ return unless opt
43
44
 
44
- found_statuses = Models::IssueStatus.all.filter_by_name_substring(options[:status])
45
+ list = Models::IssueStatus.all
46
+ if opt.numeric?
47
+ status = list.find { |s| s.id == opt }
48
+ return issue.status_id = status.id if status
49
+ end
50
+
51
+ found_statuses = list.filter_by_name_substring(opt)
45
52
  case found_statuses.size
46
53
  when 0 then @errors.push "Status: #{m(:not_found)}"
47
54
  when 1 then issue.status_id = found_statuses.first.id
@@ -22,6 +22,15 @@ module RedmineCLI
22
22
 
23
23
  puts m(:thank_you)
24
24
  end
25
+
26
+ desc 'status-complete', m('desc.conf.status_complete')
27
+ def status_complete
28
+ puts m('commands.conf.status_complete.select_status')
29
+ Config['statuses'] ||= {}
30
+ Config['statuses']['complete'] = ask_for_object(RedmineRest::Models::IssueStatus.all).id
31
+ Config.save
32
+ puts m(:thank_you)
33
+ end
25
34
  end
26
35
  end
27
36
  end
@@ -1,5 +1,6 @@
1
1
  require 'thor'
2
2
  require 'redmine_rest'
3
+ require_relative 'conf'
3
4
 
4
5
  module RedmineCLI
5
6
  module Subcommands
@@ -24,13 +25,33 @@ module RedmineCLI
24
25
 
25
26
  desc 'show <id>', m('desc.issue.show')
26
27
  option :limit, aliases: ['-l'], type: :numeric, default: 5, desc: m('desc.issue.options.show.limit')
28
+ option :comments_only, aliases: ['-c'], type: :boolean, desc: m('desc.issue.options.show.comments')
27
29
  def show(id)
28
- puts erb('issue/show', issue: Models::Issue.find(id), journals_limit: options[:limit])
30
+ puts erb 'issue/show',
31
+ issue: Models::Issue.find(id),
32
+ journals_limit: options[:limit],
33
+ comments_only: options[:comments_only]
29
34
 
30
35
  rescue ActiveResource::ResourceNotFound # WARNING: it can be raised by associations in template
31
36
  puts m(:not_found)
32
37
  end
33
38
 
39
+ desc 'complete <id>', m('desc.issue.complete')
40
+ option :assign, aliases: ['-a'], type: :string, desc: m('desc.issue.options.complete.assign')
41
+ def complete(id)
42
+ issue = Models::Issue.find(id)
43
+ invoke(Conf, 'status_complete', []) unless Config['statuses'] && Config['statuses']['complete']
44
+ assign_to = if options[:assign]
45
+ InputParser.parse_user(options[:assign], project: issue.project).id
46
+ else
47
+ issue.author.id
48
+ end
49
+
50
+ invoke(:update, [id], ['-d', '100', '-s', Config['statuses']['complete'], '-c', '-a', assign_to])
51
+ rescue ActiveResource::ResourceNotFound
52
+ puts m(:not_found)
53
+ end
54
+
34
55
  #
35
56
  # TODO:
36
57
  # * estimated time
@@ -69,7 +90,6 @@ module RedmineCLI
69
90
 
70
91
  @issue = Models::Issue.new
71
92
  set_attributes
72
-
73
93
  @issue.save
74
94
  puts 'Done.'
75
95
  end
@@ -34,7 +34,7 @@ module RedmineCLI
34
34
  end
35
35
 
36
36
  def method_missing(m, *args)
37
- return @vars[m] if args.empty? && @vars[m]
37
+ return @vars[m] if args.empty? && @vars.key?(m)
38
38
 
39
39
  super
40
40
  end
@@ -1,3 +1,3 @@
1
1
  module RedmineCLI
2
- VERSION = '0.5.1'.freeze
2
+ VERSION = '0.6.0'.freeze
3
3
  end
data/redmine_cli.gemspec CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
 
28
28
  spec.add_dependency 'thor', '~> 0.19'
29
29
  spec.add_dependency 'i18n', '~> 0.7'
30
- spec.add_dependency 'redmine_rest', '0.7.0'
30
+ spec.add_dependency 'redmine_rest', '0.8.0'
31
31
  spec.add_dependency 'non_config', '0.1.2'
32
32
  spec.add_dependency 'colorize', '~> 0.7'
33
33
  spec.add_dependency 'unicode', '~> 0.4'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redmine_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitriy Non
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-08 00:00:00.000000000 Z
11
+ date: 2016-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - '='
102
102
  - !ruby/object:Gem::Version
103
- version: 0.7.0
103
+ version: 0.8.0
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - '='
109
109
  - !ruby/object:Gem::Version
110
- version: 0.7.0
110
+ version: 0.8.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: non_config
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -174,6 +174,12 @@ files:
174
174
  - lib/assets/templates/en/id_and_name_list.erb
175
175
  - lib/assets/templates/en/issue/list.erb
176
176
  - lib/assets/templates/en/issue/show.erb
177
+ - lib/assets/templates/en/issue/show/detail.erb
178
+ - lib/assets/templates/en/issue/show/detail/some_object.erb
179
+ - lib/assets/templates/en/issue/show/detail/status.erb
180
+ - lib/assets/templates/en/issue/show/detail/user.erb
181
+ - lib/assets/templates/en/issue/show/journals.erb
182
+ - lib/assets/templates/en/issue/show/user.erb
177
183
  - lib/assets/templates/en/user/find.erb
178
184
  - lib/redmine_cli.rb
179
185
  - lib/redmine_cli/config.rb
@@ -211,7 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
211
217
  version: '0'
212
218
  requirements: []
213
219
  rubyforge_project:
214
- rubygems_version: 2.4.6
220
+ rubygems_version: 2.5.1
215
221
  signing_key:
216
222
  specification_version: 4
217
223
  summary: CLI for Redmine