redmine_cli 0.4.1 → 0.5.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: bc624f0adc7b3abfb235b72185d411a86b58185b
4
- data.tar.gz: 00c6f9dbd1619f0ec3b02737e4572a2b4e872121
3
+ metadata.gz: 32498eec5c1276546c816822dde138b72a826d22
4
+ data.tar.gz: 50336d81f2a26124ea63d2b2ed48d7fcdd0bb38d
5
5
  SHA512:
6
- metadata.gz: 365203c3d24ef79f74b270c55e4c2a8be5dd5f66b1f82266de543ed6f2c01d5242331881b19572043b5e1816ed98e7f99bbb7bd0267b084c654f31ba3b76f0e7
7
- data.tar.gz: e496799303f3561a3f90152613b113641eb5ded66cea3ea0a95924ef152d624d59c1dfabc15bbfbfb03c3b33cedd9c47e4b0f20b0cd4b752b2dbb8e667039632
6
+ metadata.gz: 248f44ffd06f6d859a850d2026c94ab4f9bb2b431679e3dbc3c6452f9b7de2a9c08946d33d0bf8cde8e1802c6618840e63d27fe9e009061db94d8b5c3e3f3079
7
+ data.tar.gz: ae9920568649936d6eeaa43cc448cd61b23f7d1c05064a7867191b60cf124001a4e1c8d1f290c9a345bc84c80c2f9c9b362cb4cffa89871287c205b58520cae2
data/README.md CHANGED
@@ -22,6 +22,19 @@ Why? 'cause web-browser + mouse sucks
22
22
  redmine user find 123
23
23
  redmine user find pupkin@yet.another.mail.com
24
24
 
25
+ redmine project list
26
+ redmine project members 1
27
+ redmine project members trololo
28
+
29
+ Don't forget about console aliases!
30
+ I use something like this:
31
+
32
+ # alias i='redmine issue'
33
+ # by the way, Thor can guess your commands so:
34
+
35
+ $ i s 123
36
+ $ i u --assign 'vasya pupkin'
37
+
25
38
 
26
39
  ## Contributing
27
40
 
@@ -4,6 +4,7 @@ en:
4
4
  issue: 'Works with issues. See "redmine issue help"'
5
5
  conf: 'Works with config file. See "redmine conf help"'
6
6
  user: 'Works with users. See "redmine user help"'
7
+ project: 'Works with projects. See "redmine project help"'
7
8
  issue:
8
9
  list: 'Lists issues of user. By default it is you'
9
10
  show: 'More info about issue'
@@ -14,7 +15,7 @@ en:
14
15
  limit: 'Amount of comments (last journals).'
15
16
  update:
16
17
  done: 'Readiness percentage'
17
- assign: 'ID of user issue will be assigned to'
18
+ assign: 'ID of name part of user issue will be assigned to'
18
19
  time: 'Add time entry. Formats: HH:MM; M (minutes); H.h (hours in float)'
19
20
  status: 'Change status of issue. Search by status name substring'
20
21
  comment: 'Leave comment. It will open your text editor.'
@@ -23,7 +24,9 @@ en:
23
24
  init: 'Asks you few question to make your config file useful'
24
25
  user:
25
26
  find: 'Finds users by id|email|name. Without arguments it will show your info'
26
-
27
+ project:
28
+ list: 'Just lists project name with IDs'
29
+ members: 'Lists members of given project'
27
30
  commands:
28
31
  conf:
29
32
  init:
@@ -0,0 +1,16 @@
1
+ % if list.size.zero?
2
+ Empty list
3
+ % end
4
+ %
5
+ %
6
+ % head_id = '(id)'
7
+ % max_id_len = list.map(&:id).map(&:size).max || 0
8
+ % max_id_len = [max_id_len, head_id.size].max
9
+ %
10
+ % head_name = '(name)'
11
+ %
12
+ <%= head_id.yellow %> | <%= head_name.yellow %>
13
+
14
+ % list.each do |object|
15
+ <%= object.id.rjust(max_id_len) %> - <%= object.name %><%= "\n" %>
16
+ % end
@@ -32,6 +32,14 @@
32
32
  * <%= issue_id == issue.id ? 'this' : issue_id %> <%= relation_type %> <%= issue_to_id == issue.id ? 'this' : issue_to_id %>
33
33
  % end
34
34
 
35
+ % end
36
+ %
37
+ % if issue.attachments?
38
+ <%= 'Attachments:'.yellow %>
39
+
40
+ % issue.attachments.each do |a|
41
+ <%= '*'.yellow %> <%= a.filename %> - <%= a.content_url %>
42
+ % end
35
43
  % end
36
44
  %
37
45
  % if issue.description? && !issue.description.empty?
@@ -1,4 +1,5 @@
1
1
  module RedmineCLI
2
+ class ProjectNotFound < StandardError; end
2
3
  class UserNotFound < StandardError; end
3
4
  class BadInputTime < StandardError; end
4
5
  class EmptyList < StandardError; end
@@ -12,16 +12,10 @@ module RedmineCLI
12
12
  include Helpers::Output
13
13
 
14
14
  def ask_for_user(message, params = {})
15
- params[:limited_to] = proc do |input|
16
- begin
17
- @ask_for_user_cache = RedmineRest::Models::User.find(input) # save record
18
- rescue
19
- nil
20
- end
21
- end
15
+ params[:limited_to] = ->(input) { @cached_user = RedmineRest::Models::User.find_by_id(input) }
22
16
 
23
17
  ask(message, params)
24
- @ask_for_user_cache
18
+ @cached_user
25
19
  end
26
20
 
27
21
  def ask_from_text_editor(welcome_message = '')
@@ -58,25 +52,6 @@ module RedmineCLI
58
52
  object_list[input.to_i]
59
53
  end
60
54
 
61
- #
62
- # Parses time from user's input.
63
- # Formats: HH:MM; M; H.h
64
- #
65
- # @param input [String]
66
- #
67
- def parse_time(input)
68
- fail(BadInputTime) unless input =~ /^\d+[\:\.]?\d*/
69
-
70
- if input.include?(':')
71
- h, m = input.split(':').map(&:to_i)
72
- (60 * h + m) / 60.0
73
- elsif input.include?('.')
74
- input.to_f
75
- else
76
- input.to_i
77
- end
78
- end
79
-
80
55
  #
81
56
  # #ask with :limited_to set to url regexp.
82
57
  # TODO: make good regexp
@@ -32,12 +32,9 @@ module RedmineCLI
32
32
 
33
33
  def update_assigned_to(issue)
34
34
  return unless options[:assign]
35
+ issue.assigned_to_id = InputParser.parse_user(options[:assign], project: issue.project).id
35
36
 
36
- # it can raise exception if there's no such user
37
- Models::User.find(options[:assign])
38
- issue.assigned_to_id = options[:assign]
39
-
40
- rescue ActiveResource::ResourceNotFound
37
+ rescue UserNotFound
41
38
  @errors.push "Assigned: #{m(:not_found)}"
42
39
  end
43
40
 
@@ -70,7 +67,7 @@ module RedmineCLI
70
67
  def add_time_entry_to_issue(issue)
71
68
  return unless options[:time]
72
69
 
73
- hours = parse_time(options[:time])
70
+ hours = InputParser.parse_time(options[:time])
74
71
  entry = Models::TimeEntry.create issue_id: issue.id,
75
72
  hours: hours
76
73
 
@@ -7,4 +7,10 @@ class String
7
7
 
8
8
  self[0...max_chars - 3] + '...'
9
9
  end
10
+
11
+ def numeric?
12
+ Integer(self)
13
+ rescue
14
+ false
15
+ end
10
16
  end
@@ -0,0 +1,71 @@
1
+ module RedmineCLI
2
+ #
3
+ # class with some methods for user input processing
4
+ #
5
+ class InputParser
6
+ extend Helpers::Input
7
+
8
+ #
9
+ # Processes string and tries to find project
10
+ #
11
+ def self.parse_project(value)
12
+ by_id = RedmineRest::Models::Project.find_by_id(value) if value.numeric?
13
+ return by_id if by_id
14
+
15
+ found_projects = RedmineRest::Models::Project.all.filter_by_name_substring(value)
16
+ case found_projects.size
17
+ when 0 then fail(ProjectNotFound)
18
+ when 1 then found_projects.first
19
+ else ask_for_object(found_projects)
20
+ end
21
+
22
+ rescue ActiveResource::ResourceNotFound, ActiveResource::ForbiddenAccess
23
+ raise ProjectNotFound
24
+ end
25
+
26
+ #
27
+ # Processes string and tries to find user
28
+ #
29
+ # @return [RedmineRest::Models::User]
30
+ # @raise [UserNotFound]
31
+ #
32
+ def self.parse_user(value, project: nil)
33
+ return RedmineRest::Models::User.find(value) if value.numeric? || value == 'current'
34
+ fail UserNotFound unless project
35
+
36
+ user_from_project(project, value)
37
+
38
+ rescue ActiveResource::ResourceNotFound
39
+ raise UserNotFound
40
+ end
41
+
42
+ def self.user_from_project(project, name_substring = '')
43
+ found_members = project.members.filter_by_name_substring(name_substring)
44
+
45
+ case found_members.size
46
+ when 0 then fail(UserNotFound)
47
+ when 1 then found_members.first
48
+ else ask_for_object(found_members)
49
+ end
50
+ end
51
+
52
+ #
53
+ # Parses time from user's input.
54
+ # Formats: HH:MM; M; H.h
55
+ #
56
+ # @param input [String]
57
+ #
58
+ def self.parse_time(input)
59
+ fail(BadInputTime) unless input =~ /^\d+[\:\.]?\d*/
60
+
61
+ if input.include?(':')
62
+ h, m = input.split(':').map(&:to_i)
63
+ (60 * h + m) / 60.0
64
+ elsif input.include?('.')
65
+ input.to_f
66
+ else
67
+ input.to_i
68
+ end
69
+ end
70
+ end
71
+ end
@@ -16,7 +16,10 @@ module RedmineCLI
16
16
  def list(id = 'current')
17
17
  fail('new config') if Config.new?
18
18
 
19
- puts erb('issue/list', issues: Models::User.find(id).issues)
19
+ user = InputParser.parse_user(id)
20
+ puts erb('issue/list', issues: user.issues)
21
+ rescue UserNotFound
22
+ puts "User #{m(:not_found)}"
20
23
  end
21
24
 
22
25
  desc 'show <id>', m('desc.issue.show')
@@ -40,7 +43,7 @@ module RedmineCLI
40
43
  #
41
44
  desc 'update <id>', m('desc.issue.update')
42
45
  option :done, type: :numeric, aliases: '-d', desc: m('desc.issue.options.update.done')
43
- option :assign, type: :numeric, aliases: '-a', desc: m('desc.issue.options.update.assign')
46
+ option :assign, type: :string, aliases: '-a', desc: m('desc.issue.options.update.assign')
44
47
  option :time, type: :string, aliases: '-t', desc: m('desc.issue.options.update.time')
45
48
  option :status, type: :string, aliases: '-s', desc: m('desc.issue.options.update.status')
46
49
  option :comment, type: :boolean, aliases: '-c', desc: m('desc.issue.options.update.comment')
@@ -0,0 +1,36 @@
1
+ require 'thor'
2
+ require 'redmine_rest'
3
+ module RedmineCLI
4
+ module Subcommands
5
+ #
6
+ # Methods for working with projects
7
+ #
8
+ class Project < Thor
9
+ extend Helpers::Output
10
+
11
+ include RedmineRest
12
+ include Helpers::Output
13
+ include Helpers::Input
14
+
15
+ map 'users' => 'members'
16
+
17
+ desc 'list', m('desc.project.list')
18
+ def list
19
+ puts erb('id_and_name_list', list: Models::Project.all)
20
+ end
21
+
22
+ desc 'members <id | name part>', m('desc.project.members')
23
+ def members(project)
24
+ project = InputParser.parse_project(project)
25
+
26
+ users = project.members
27
+ .map(&:reload)
28
+ .sort { |a, b| a.id.to_i <=> b.id.to_i }
29
+
30
+ puts erb('user/find', users: users)
31
+ rescue ProjectNotFound
32
+ puts "Project #{m(:not_found)}"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,3 @@
1
1
  module RedmineCLI
2
- VERSION = '0.4.1'.freeze
2
+ VERSION = '0.5.0'.freeze
3
3
  end
data/lib/redmine_cli.rb CHANGED
@@ -10,6 +10,7 @@ Dir[File.expand_path('../redmine_cli/helpers/**/*.rb', __FILE__)].each { |f| req
10
10
  require 'redmine_cli/version'
11
11
  require 'redmine_cli/exceptions'
12
12
  require 'redmine_cli/config'
13
+ require 'redmine_cli/input_parser'
13
14
  I18n.locale = RedmineCLI::Config['locale']
14
15
 
15
16
  require 'redmine_cli/template_renderer'
@@ -43,5 +44,8 @@ module RedmineCLI
43
44
 
44
45
  desc 'user ...', m('desc.client.user')
45
46
  subcommand 'user', Subcommands::User
47
+
48
+ desc 'project ...', m('desc.client.project')
49
+ subcommand 'project', Subcommands::Project
46
50
  end
47
51
  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.6.1'
30
+ spec.add_dependency 'redmine_rest', '0.7.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.4.1
4
+ version: 0.5.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-03-25 00:00:00.000000000 Z
11
+ date: 2016-03-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.6.1
103
+ version: 0.7.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.6.1
110
+ version: 0.7.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: non_config
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -171,6 +171,7 @@ files:
171
171
  - exe/redmine
172
172
  - lib/assets/default_config.yml
173
173
  - lib/assets/messages/en.yml
174
+ - lib/assets/templates/en/id_and_name_list.erb
174
175
  - lib/assets/templates/en/issue/list.erb
175
176
  - lib/assets/templates/en/issue/show.erb
176
177
  - lib/assets/templates/en/user/find.erb
@@ -182,8 +183,10 @@ files:
182
183
  - lib/redmine_cli/helpers/issue/update.rb
183
184
  - lib/redmine_cli/helpers/monkey_patching.rb
184
185
  - lib/redmine_cli/helpers/output.rb
186
+ - lib/redmine_cli/input_parser.rb
185
187
  - lib/redmine_cli/subcommands/conf.rb
186
188
  - lib/redmine_cli/subcommands/issue.rb
189
+ - lib/redmine_cli/subcommands/project.rb
187
190
  - lib/redmine_cli/subcommands/user.rb
188
191
  - lib/redmine_cli/template_renderer.rb
189
192
  - lib/redmine_cli/version.rb