From 29cc65cbc0d6e1bc3949f2c314a2461f2b4bc31e Mon Sep 17 00:00:00 2001 From: supersimple Date: Tue, 20 Dec 2016 15:28:02 -0700 Subject: [PATCH 1/6] fixes grammar and misspelling in readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 060cfdc..960fa05 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,11 @@ # Terjira -Terjira is an interactive and easy to use command line interface (or Application) for Jira. You do not need to remember resource key or id. Terjira suggests it with interactive prompt. +Terjira is an interactive and easy to use command line interface (or Application) for Jira. You do not need to remember the resource key or id. Terjira suggests it with an interactive prompt. Your Jira must support Rest API 2.0 and Agile Rest API 1.0 -## Domo +## Demo [Watch full demo](https://www.youtube.com/watch?v=T0hbhaXtH-Y) [![Sample](./dev/demo.gif)](https://www.youtube.com/watch?v=T0hbhaXtH-Y) From fbb0f782ce935de5afe292e817c7aa8e9bc23a60 Mon Sep 17 00:00:00 2001 From: keepcosmos Date: Mon, 26 Dec 2016 20:14:07 +0900 Subject: [PATCH 2/6] fix #10 --- .gitignore | 2 ++ lib/terjira/base_cli.rb | 9 +-------- lib/terjira/client/issue.rb | 2 +- lib/terjira/client/status_category.rb | 20 ++++++++++++++++++++ lib/terjira/ext/jira_ruby.rb | 27 +++++++++++++++++++++------ lib/terjira/issue_cli.rb | 8 +++++++- 6 files changed, 52 insertions(+), 16 deletions(-) create mode 100644 lib/terjira/client/status_category.rb diff --git a/.gitignore b/.gitignore index 48aaefe..e38e500 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +full_test + .vagrant *.gem diff --git a/lib/terjira/base_cli.rb b/lib/terjira/base_cli.rb index 135494a..9df2336 100644 --- a/lib/terjira/base_cli.rb +++ b/lib/terjira/base_cli.rb @@ -2,16 +2,9 @@ require_relative 'option_supportable' Dir[File.dirname(__FILE__) + '/presenters/*.rb'].each { |f| require f } +Dir[File.dirname(__FILE__) + '/client/*.rb'].each { |f| require f } module Terjira - # Jira client based on jira-ruby gem - module Client - %w(Base Field Issuetype Project Board Sprint Issue User - Status Resolution Priority RapidView Agile).each do |klass| - autoload klass, "terjira/client/#{klass.gsub(/(.)([A-Z](?=[a-z]))/,'\1_\2').downcase}" - end - end - class BaseCLI < Thor include OptionSupportable diff --git a/lib/terjira/client/issue.rb b/lib/terjira/client/issue.rb index 7515b81..18b9440 100644 --- a/lib/terjira/client/issue.rb +++ b/lib/terjira/client/issue.rb @@ -4,7 +4,7 @@ module Terjira module Client class Issue < Base class << self - delegate :build, :find, to: :resource + delegate :find, to: :resource def all(options = {}) return resource.all if options.blank? diff --git a/lib/terjira/client/status_category.rb b/lib/terjira/client/status_category.rb new file mode 100644 index 0000000..e9937d1 --- /dev/null +++ b/lib/terjira/client/status_category.rb @@ -0,0 +1,20 @@ +require_relative 'base' + +module Terjira + module Client + class StatusCategory < Base + class << self + def all + @all_statuscategory ||= file_cache.fetch("all") do + resp = api_get "statuscategory" + resp.map { |category| build(category) } + end + end + + def file_cache + Terjira::FileCache.new("resource/statuscategory", 60 * 60 * 48) + end + end + end + end +end diff --git a/lib/terjira/ext/jira_ruby.rb b/lib/terjira/ext/jira_ruby.rb index dc76e61..1d67ea2 100644 --- a/lib/terjira/ext/jira_ruby.rb +++ b/lib/terjira/ext/jira_ruby.rb @@ -27,12 +27,6 @@ def key_with_key_value end module Resource - class BoardFactory < JIRA::BaseFactory # :nodoc: - end - - class EpicFactory < JIRA::BaseFactory # :nodoc: - end - class Board < JIRA::Base def self.key_attribute; :id; end end @@ -41,6 +35,10 @@ class Epic < JIRA::Base def self.key_attribute; :key; end end + class StatusCategory < JIRA::Base + def self.key_attribute; :name; end + end + class User def self.key_attribute; :name; end end @@ -60,12 +58,29 @@ def self.key_attribute; :name; end class Resolution def self.key_attribute; :name; end end + + class BoardFactory < JIRA::BaseFactory + end + + class EpicFactory < JIRA::BaseFactory + end + + class StatusCategoryFactory < JIRA::BaseFactory + end end class Client def Board # :nodoc: JIRA::Resource::BoardFactory.new(self) end + + def Epic + JIRA::Resource::EpicFactory.new(self) + end + + def StatusCategory + JIRA::Resource::StatusCategoryFactory.new(self) + end end end diff --git a/lib/terjira/issue_cli.rb b/lib/terjira/issue_cli.rb index ad78704..a76c97d 100644 --- a/lib/terjira/issue_cli.rb +++ b/lib/terjira/issue_cli.rb @@ -34,7 +34,7 @@ def open(issue) map ls: :list def list opts = suggest_options - opts[:statusCategory] ||= %w(To\ Do In\ Progress) unless opts[:status] + opts[:statusCategory] ||= default_status_categories unless opts[:status] opts[:assignee] ||= current_username opts.delete(:assignee) if opts[:assignee] =~ /^all/i @@ -121,5 +121,11 @@ def trans(*args) issue = client_class.trans(issue, opts) render_issue_detail(issue) end + + no_commands do + def default_status_categories + Client::StatusCategory.all.reject { |category| category.key =~ /done/i }.map(&:name) + end + end end end From 1783ec6b77d94a466d88d6c8a5320494ea1ea0d9 Mon Sep 17 00:00:00 2001 From: keepcosmos Date: Mon, 26 Dec 2016 21:51:56 +0900 Subject: [PATCH 3/6] Add Story points column on issue detail #8 --- lib/terjira/client/field.rb | 18 ++- lib/terjira/option_supportable.rb | 2 +- lib/terjira/presenters/issue_presenter.rb | 35 ++++-- lib/terjira/presenters/sprint_presenter.rb | 2 +- spec/client/field_spec.rb | 29 +++++ spec/issue_cli_spec.rb | 4 + spec/mock_resource.rb | 12 ++ spec/mock_responses/field.json | 32 ----- spec/mock_responses/fields.json | 136 +++++++++++++++++++++ spec/mock_responses/status_categories.json | 30 +++++ 10 files changed, 251 insertions(+), 49 deletions(-) create mode 100644 spec/client/field_spec.rb delete mode 100644 spec/mock_responses/field.json create mode 100644 spec/mock_responses/fields.json create mode 100644 spec/mock_responses/status_categories.json diff --git a/lib/terjira/client/field.rb b/lib/terjira/client/field.rb index 3550cf6..b214b6b 100644 --- a/lib/terjira/client/field.rb +++ b/lib/terjira/client/field.rb @@ -3,6 +3,8 @@ module Terjira module Client class Field < Base + CACHE_PATH = "resource/fields".freeze + class << self def all @all_fields ||= file_cache.fetch("all") do @@ -14,16 +16,24 @@ def find_by_key(key) all.find { |field| field.key == key } end + def find_by_name(name) + all.find { |field| field.name == name } + end + def epic_name - all.find { |field| field.name == 'Epic Name' } + find_by_name('Epic Name') + end + + def epic_link + find_by_name('Epic Link') end - def epiclink - all.find { |field| field.name == 'Epic Link' } + def story_points + find_by_name('Story Points') end def file_cache - Terjira::FileCache.new("resource/fields", 60 * 60 * 24) + Terjira::FileCache.new(CACHE_PATH, 60 * 60 * 24) end end end diff --git a/lib/terjira/option_supportable.rb b/lib/terjira/option_supportable.rb index 256122c..0ce5e6c 100644 --- a/lib/terjira/option_supportable.rb +++ b/lib/terjira/option_supportable.rb @@ -90,7 +90,7 @@ def suggest_related_value_options(opts = {}) end if opts[:epiclink] - epiclink_field = Client::Field.epiclink + epiclink_field = Client::Field.epic_link opts[epiclink_field.key] ||= opts.delete(:epiclink) end diff --git a/lib/terjira/presenters/issue_presenter.rb b/lib/terjira/presenters/issue_presenter.rb index d3a01cf..be42a82 100644 --- a/lib/terjira/presenters/issue_presenter.rb +++ b/lib/terjira/presenters/issue_presenter.rb @@ -64,9 +64,10 @@ def issue_detail_template <%= pastel.underline.bold(issue.summary) %> - <%= bold('Type') %>: <%= colorize_issue_type(issue.issuetype) %>\s\s\s<%= bold('Status') %>: <%= colorize_issue_stastus(issue.status) %>\s\s\s<%= bold('priority') %>: <%= colorize_priority(issue.priority, title: true) %> + <%= bold('Type') %>: <%= colorize_issue_type(issue.issuetype) %>\s\s\s<%= bold('Status') %>: <%= colorize_issue_stastus(issue.status) %>\s\s\s<%= bold('Priority') %>: <%= colorize_priority(issue.priority, title: true) %> <% if issue.parent.nil? -%> - <%= bold('Epic Link') %>: <%= issue.try(:epic).try(:key) %> <%= issue.try(:epic).try(:name) || dim_none %> + + <%= bold('Epic Link') %>: <%= issue.try(:epic).try(:key) %> <%= issue.try(:epic).try(:name) || dim_none %> <% end -%> <% if issue.try(:parent) && issue.epic.nil? -%> <%= bold('Parent') %>: <%= issue.parent.key %> @@ -74,21 +75,16 @@ def issue_detail_template <% if issue.try(:sprint) -%> <%= bold('Sprint') %>: <%= colorize_sprint_state(issue.try(:sprint).try(:state)) %> <%= issue.try(:sprint).try(:id) %>. <%= issue.try(:sprint).try(:name) %> <% end -%> + <% if estimate = issue_estimate(issue) -%> + + <%= estimate[0] %>: <%= estimate[1] %> + <% end -%> <%= bold('Assignee') %>: <%= username(issue.assignee) %> <%= bold('Reporter') %>: <%= username(issue.reporter) %> <%= bold('Description') %> <%= issue.description || dim_none %> - <% if issue.try(:timetracking).is_a? Hash -%> - - <%= bold('Estimate') %> - <% if issue.timetracking['originalEstimate'] -%> - <%= issue.timetracking['originalEstimate'] %> / <%= issue.timetracking['remainingEstimate'] %> - <% else -%> - <%= dim_none %> - <% end -%> - <% end -%> <% if issue.try(:environment) -%> <%= bold('Environment') %> @@ -184,6 +180,23 @@ def colorize_priority(priority, opts = {}) pastel.decorate(title, infos[0]) end + # Extract estimate or story points + # @return Array, first element is title and second is value + def issue_estimate(issue) + field = Client::Field.story_points + story_points = issue.try(field.key) if field.respond_to? :key + return [bold('Story Points'), story_points] if story_points + + return unless issue.try(:timetracking).is_a? Hash + + if origin = issue.timetracking['originalEstimate'] + remain = issue.timetracking['remainingEstimate'] + [bold('Estimate'), "#{remain} / #{origin}"] + else + [bold('Estimate'), dim_none] + end + end + def extract_status_names(issues) issue_names = issues.sort_by do |issue| status_key = %w(new indeterminate done) diff --git a/lib/terjira/presenters/sprint_presenter.rb b/lib/terjira/presenters/sprint_presenter.rb index 7e03857..9a3bd5b 100644 --- a/lib/terjira/presenters/sprint_presenter.rb +++ b/lib/terjira/presenters/sprint_presenter.rb @@ -41,7 +41,7 @@ def summarise_sprint(sprint) end def colorize_sprint_state(state) - state = state.to_s.capitalize + state = " #{state.to_s.capitalize} " if state =~ /active/i pastel.on_blue.bold(state) elsif state =~ /close/i diff --git a/spec/client/field_spec.rb b/spec/client/field_spec.rb new file mode 100644 index 0000000..4650a59 --- /dev/null +++ b/spec/client/field_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' +require 'terjira/client/field' +require 'terjira/utils/file_cache' + +describe Terjira::Client::Field do + let(:fields) { MockResource.fields } + + before :each do + allow(described_class).to receive(:all).and_return(fields) + end + + it 'find by key' do + field = described_class.find_by_key('issuetype') + expect(field.key).to eq 'issuetype' + expect(field.name).to eq 'Issue Type' + end + + it 'find by name' do + field = described_class.find_by_name('Story Points') + expect(field.key).to eq 'customfield_10022' + expect(field.name).to eq 'Story Points' + end + + it 'find by named field method' do + expect(described_class.epic_name).to be_present + expect(described_class.epic_link).to be_present + expect(described_class.story_points).to be_present + end +end diff --git a/spec/issue_cli_spec.rb b/spec/issue_cli_spec.rb index 5e81d33..0fe5382 100644 --- a/spec/issue_cli_spec.rb +++ b/spec/issue_cli_spec.rb @@ -5,10 +5,14 @@ let(:boards) { MockResource.boards } let(:sprints) { MockResource.sprints } let(:issues) { MockResource.issues } + let(:fields) { MockResource.fields } + let(:status_categories) { MockResource.status_categories } before :each do allow(TTY::Screen).to receive(:width).and_return(10**4) allow(TTY::Prompt).to receive(:new).and_return(prompt) + allow(Terjira::Client::Field).to receive(:all).and_return(fields) + allow(Terjira::Client::StatusCategory).to receive(:all).and_return(status_categories) end context '#show' do diff --git a/spec/mock_resource.rb b/spec/mock_resource.rb index 513cce0..7e024d6 100644 --- a/spec/mock_resource.rb +++ b/spec/mock_resource.rb @@ -44,6 +44,18 @@ def priorities end end + def fields + load_response('fields').map do |field| + Terjira::Client::Field.build(field) + end + end + + def status_categories + load_response('status_categories').map do |field| + Terjira::Client::StatusCategory.build(field) + end + end + def resolutions load_response('resolutions').map do |resolution| Terjira::Client::Resolution.build(resolution) diff --git a/spec/mock_responses/field.json b/spec/mock_responses/field.json deleted file mode 100644 index a40ea3d..0000000 --- a/spec/mock_responses/field.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "id": "1", - "name": "Description", - "custom": false, - "orderable": true, - "navigable": true, - "searchable": true, - "clauseNames": [ - "description" - ], - "schema": { - "type": "string", - "system": "description" - } - }, - { - "id": "2", - "name": "Summary", - "custom": false, - "orderable": true, - "navigable": true, - "searchable": true, - "clauseNames": [ - "summary" - ], - "schema": { - "type": "string", - "system": "summary" - } - } -] \ No newline at end of file diff --git a/spec/mock_responses/fields.json b/spec/mock_responses/fields.json new file mode 100644 index 0000000..885326f --- /dev/null +++ b/spec/mock_responses/fields.json @@ -0,0 +1,136 @@ +[ + { + "id": "issuetype", + "key": "issuetype", + "name": "Issue Type", + "custom": false, + "orderable": true, + "navigable": true, + "searchable": true, + "clauseNames": [ + "issuetype", + "type" + ], + "schema": { + "type": "issuetype", + "system": "issuetype" + } + }, + { + "id": "timespent", + "key": "timespent", + "name": "Time Spent", + "custom": false, + "orderable": false, + "navigable": true, + "searchable": false, + "clauseNames": [ + "timespent" + ], + "schema": { + "type": "number", + "system": "timespent" + } + }, + { + "id": "project", + "key": "project", + "name": "Project", + "custom": false, + "orderable": false, + "navigable": true, + "searchable": true, + "clauseNames": [ + "project" + ], + "schema": { + "type": "project", + "system": "project" + } + }, + { + "id": "fixVersions", + "key": "fixVersions", + "name": "Fix Version/s", + "custom": false, + "orderable": true, + "navigable": true, + "searchable": true, + "clauseNames": [ + "fixVersion" + ], + "schema": { + "type": "array", + "items": "version", + "system": "fixVersions" + } + }, + { + "id": "aggregatetimespent", + "key": "aggregatetimespent", + "name": "Σ Time Spent", + "custom": false, + "orderable": false, + "navigable": true, + "searchable": false, + "clauseNames": [], + "schema": { + "type": "number", + "system": "aggregatetimespent" + } + }, + { + "id": "customfield_10022", + "key": "customfield_10022", + "name": "Story Points", + "custom": true, + "orderable": true, + "navigable": true, + "searchable": true, + "clauseNames": [ + "cf[10022]", + "Story Points" + ], + "schema": { + "type": "number", + "custom": "com.atlassian.jira.plugin.system.customfieldtypes:float", + "customId": 10022 + } + }, + { + "id": "customfield_10018", + "key": "customfield_10018", + "name": "Epic Link", + "custom": true, + "orderable": true, + "navigable": true, + "searchable": true, + "clauseNames": [ + "cf[10018]", + "Epic Link" + ], + "schema": { + "type": "any", + "custom": "com.pyxis.greenhopper.jira:gh-epic-link", + "customId": 10018 + } + }, + { + "id": "customfield_10020", + "key": "customfield_10020", + "name": "Epic Name", + "custom": true, + "orderable": true, + "navigable": true, + "searchable": true, + "clauseNames": [ + "cf[10020]", + "Epic Name" + ], + "schema": { + "type": "string", + "custom": "com.pyxis.greenhopper.jira:gh-epic-label", + "customId": 10020 + } + } +] diff --git a/spec/mock_responses/status_categories.json b/spec/mock_responses/status_categories.json new file mode 100644 index 0000000..b2ec5d1 --- /dev/null +++ b/spec/mock_responses/status_categories.json @@ -0,0 +1,30 @@ +[ + { + "self": "https://myrealtrip.atlassian.net/rest/api/2/statuscategory/1", + "id": 1, + "key": "undefined", + "colorName": "medium-gray", + "name": "No Category" + }, + { + "self": "https://myrealtrip.atlassian.net/rest/api/2/statuscategory/2", + "id": 2, + "key": "new", + "colorName": "blue-gray", + "name": "To Do" + }, + { + "self": "https://myrealtrip.atlassian.net/rest/api/2/statuscategory/4", + "id": 4, + "key": "indeterminate", + "colorName": "yellow", + "name": "In Progress" + }, + { + "self": "https://myrealtrip.atlassian.net/rest/api/2/statuscategory/3", + "id": 3, + "key": "done", + "colorName": "green", + "name": "Done" + } +] From c3bd19033cafdee08052c0b0d33f8f6ec73d082f Mon Sep 17 00:00:00 2001 From: keepcosmos Date: Mon, 26 Dec 2016 22:36:15 +0900 Subject: [PATCH 4/6] Add JQL issue search --- README.md | 5 ++++- lib/terjira/client/issue.rb | 4 ++-- lib/terjira/issue_cli.rb | 9 +++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 960fa05..941a21c 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,9 @@ Issue: # default assignee option is current loggined user # To show issues of all users(include no assignee)                                     # pass `--assignee ALL` option. + jira issue jql "[QUERY]" # Search issues with JQL + # ex) + # jira issue jql "project = 'TEST' AND summary ~ 'authentication'" jira issue [ISSUE_KEY] # Show detail of the issue jira issue assign [ISSUE_KEY] ([ASSIGNEE]) # Assign the issue to user jira issue comment [ISSUE_KEY] # Write comment on the issue @@ -72,7 +75,7 @@ Issue: ## Todo **Contributions are welcome!** -- [ ] Add JQL command for find issues +- [x] Add JQL command for find issues - [ ] Manage worklog and estimate of issues - [ ] Manage component and version of issues - [ ] Track history of transitions diff --git a/lib/terjira/client/issue.rb b/lib/terjira/client/issue.rb index 18b9440..926fcf8 100644 --- a/lib/terjira/client/issue.rb +++ b/lib/terjira/client/issue.rb @@ -4,12 +4,12 @@ module Terjira module Client class Issue < Base class << self - delegate :find, to: :resource + delegate :jql, :find, to: :resource def all(options = {}) return resource.all if options.blank? max_results = options.delete(:max_results) || 500 - resource.jql(build_jql(options), max_results: max_results) + jql(build_jql(options), max_results: max_results) end def all_epic_issues(epic) diff --git a/lib/terjira/issue_cli.rb b/lib/terjira/issue_cli.rb index a76c97d..70fd14a 100644 --- a/lib/terjira/issue_cli.rb +++ b/lib/terjira/issue_cli.rb @@ -42,6 +42,15 @@ def list render_issues(issues) end + desc 'jql "[QUERY]"', "Search issues with JQL" + long_desc <<-EXAMPLE + jira issue jql "project = 'IST' AND assignee = currentuser()" + EXAMPLE + def jql(*query) + jql = query.join(" ") + render_issues Client::Issue.jql(jql) + end + desc 'new', 'Create an issue' jira_options :summary, :description, :project, :issuetype, :priority, :assignee, :parent, :epiclink From efff326b92631d502b177dee5813c05608966af1 Mon Sep 17 00:00:00 2001 From: keepcosmos Date: Mon, 26 Dec 2016 22:40:11 +0900 Subject: [PATCH 5/6] release 0.2.6 --- Gemfile.lock | 2 +- lib/terjira/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3840f9b..c8b51ec 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - terjira (0.2.5) + terjira (0.2.6) activesupport (= 4.0.13) jira-ruby (~> 1.1) pastel (~> 0.6.1) diff --git a/lib/terjira/version.rb b/lib/terjira/version.rb index bf1ba54..2b484a1 100644 --- a/lib/terjira/version.rb +++ b/lib/terjira/version.rb @@ -1,7 +1,7 @@ require 'terjira/utils/file_cache' module Terjira - VERSION = '0.2.5'.freeze + VERSION = '0.2.6'.freeze class VersionChecker VERSION_CHECK_DURATION = (60 * 60 * 24 * 5).freeze From 2009747c0eeb794d774eae2c09b67afb6d56d9b7 Mon Sep 17 00:00:00 2001 From: keepcosmos Date: Tue, 27 Dec 2016 21:29:50 +0900 Subject: [PATCH 6/6] update issue detail view --- lib/terjira/presenters/common_presenter.rb | 2 +- lib/terjira/presenters/issue_presenter.rb | 27 +++++++++++----------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/lib/terjira/presenters/common_presenter.rb b/lib/terjira/presenters/common_presenter.rb index 7776774..8b6198c 100644 --- a/lib/terjira/presenters/common_presenter.rb +++ b/lib/terjira/presenters/common_presenter.rb @@ -34,7 +34,7 @@ def username(user) if user.nil? dim_none else - "#{user.name}, #{user.displayName}" + "#{user.displayName}(#{user.name})" end end diff --git a/lib/terjira/presenters/issue_presenter.rb b/lib/terjira/presenters/issue_presenter.rb index be42a82..b460cc7 100644 --- a/lib/terjira/presenters/issue_presenter.rb +++ b/lib/terjira/presenters/issue_presenter.rb @@ -62,32 +62,31 @@ def summarise_issue(issue) def issue_detail_template %{<%= bold(issue.key) + ' in ' + issue.project.name %> - <%= pastel.underline.bold(issue.summary) %> + <%= bold(issue.summary) %> - <%= bold('Type') %>: <%= colorize_issue_type(issue.issuetype) %>\s\s\s<%= bold('Status') %>: <%= colorize_issue_stastus(issue.status) %>\s\s\s<%= bold('Priority') %>: <%= colorize_priority(issue.priority, title: true) %> + Type: <%= colorize_issue_type(issue.issuetype) %>\s\sStatus: <%= colorize_issue_stastus(issue.status) %>\s\sPriority: <%= colorize_priority(issue.priority, title: true) %> <% if issue.parent.nil? -%> - <%= bold('Epic Link') %>: <%= issue.try(:epic).try(:key) %> <%= issue.try(:epic).try(:name) || dim_none %> + Epic: <%= issue.try(:epic).try(:key) %> <%= issue.try(:epic).try(:name) || dim_none %> <% end -%> <% if issue.try(:parent) && issue.epic.nil? -%> - <%= bold('Parent') %>: <%= issue.parent.key %> + Parent: <%= issue.parent.key %> <% end %> <% if issue.try(:sprint) -%> - <%= bold('Sprint') %>: <%= colorize_sprint_state(issue.try(:sprint).try(:state)) %> <%= issue.try(:sprint).try(:id) %>. <%= issue.try(:sprint).try(:name) %> + Sprint: <%= colorize_sprint_state(issue.try(:sprint).try(:state)) %> <%= issue.try(:sprint).try(:id) %>. <%= issue.try(:sprint).try(:name) %> <% end -%> <% if estimate = issue_estimate(issue) -%> <%= estimate[0] %>: <%= estimate[1] %> <% end -%> - <%= bold('Assignee') %>: <%= username(issue.assignee) %> - <%= bold('Reporter') %>: <%= username(issue.reporter) %> + Assignee: <%= username(issue.assignee) %> + Reporter: <%= username(issue.reporter) %> - <%= bold('Description') %> - <%= issue.description || dim_none %> + <%= issue.description || dim("No description") %> <% if issue.try(:environment) -%> - <%= bold('Environment') %> + <%= Environment %>: <%= issue.environment %> <% end -%> <% if issue.try(:attachment).present? -%> @@ -116,7 +115,7 @@ def comments_template """ <% remain_comments = issue.comments -%> <% visiable_comments = remain_comments.pop(COMMENTS_SIZE) -%> - <%= bold('Comments') %> + Comments: <% if visiable_comments.empty? -%> <%= dim_none %> <% elsif remain_comments.size != 0 -%> @@ -185,15 +184,15 @@ def colorize_priority(priority, opts = {}) def issue_estimate(issue) field = Client::Field.story_points story_points = issue.try(field.key) if field.respond_to? :key - return [bold('Story Points'), story_points] if story_points + return ['Story Points', story_points] if story_points return unless issue.try(:timetracking).is_a? Hash if origin = issue.timetracking['originalEstimate'] remain = issue.timetracking['remainingEstimate'] - [bold('Estimate'), "#{remain} / #{origin}"] + ['Estimate', "#{remain} / #{origin}"] else - [bold('Estimate'), dim_none] + ['Estimate', dim_none] end end