bjira 0.0.6 → 0.0.7

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bjira",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "A simple jira CLI tool",
5
5
  "main": "src/index.js",
6
6
  "author": {
package/src/ask.js ADDED
@@ -0,0 +1,57 @@
1
+ import inquirer from 'inquirer';
2
+
3
+ class Ask {
4
+ static async askString(message, defaultValue = undefined) {
5
+ const question = {
6
+ type: 'input',
7
+ name: 'value',
8
+ message,
9
+ };
10
+
11
+ if (defaultValue !== undefined) question.default = defaultValue;
12
+ const answer = await inquirer.prompt([question]);
13
+ return answer.value;
14
+ }
15
+
16
+ static async askPassword(message) {
17
+ const answer = await inquirer.prompt([{
18
+ type: 'password',
19
+ name: 'value',
20
+ message,
21
+ }]);
22
+ return answer.value;
23
+ }
24
+
25
+ static async askBoolean(message) {
26
+ const answer = await inquirer.prompt([{
27
+ type: 'confirm',
28
+ name: 'value',
29
+ message,
30
+ }]);
31
+ return answer.value;
32
+ }
33
+
34
+ static async askNumber(message) {
35
+ const question = {
36
+ type: 'number',
37
+ name: 'value',
38
+ message,
39
+ };
40
+
41
+ const answer = await inquirer.prompt([question]);
42
+ return answer.value;
43
+ }
44
+
45
+ static async askList(message, list) {
46
+ const answer = await inquirer.prompt([{
47
+ type: 'list',
48
+ name: 'value',
49
+ message,
50
+ choices: list,
51
+ filter: name => list.indexOf(name),
52
+ }]);
53
+ return answer.value;
54
+ }
55
+ };
56
+
57
+ export default Ask;
package/src/comment.js CHANGED
@@ -1,11 +1,9 @@
1
1
  import execa from 'execa';
2
- import inquirer from 'inquirer';
3
2
  import fs from 'fs';
4
3
  import temp from 'temp';
5
4
 
6
5
  import Command from './command.js';
7
6
  import Jira from './jira.js';
8
- import ErrorHandler from './errorhandler.js';
9
7
 
10
8
  class Comment extends Command {
11
9
  addOptions(program) {
@@ -47,7 +45,7 @@ class Comment extends Command {
47
45
 
48
46
  const jira = new Jira(program);
49
47
 
50
- const data = await jira.spin('Adding the comment...', jira.api.addComment(id, comment));
48
+ await jira.spin('Adding the comment...', jira.api.addComment(id, comment));
51
49
  });
52
50
  }
53
51
  };
package/src/create.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import color from 'chalk';
2
- import inquirer from 'inquirer';
3
2
 
3
+ import Ask from './ask.js';
4
4
  import Command from './command.js';
5
5
  import Jira from './jira.js';
6
6
  import Issue from './issue.js';
7
7
  import Project from './project.js';
8
+ import Set from './set.js';
8
9
  import User from './user.js';
9
10
 
10
11
  class Create extends Command {
@@ -15,30 +16,7 @@ class Create extends Command {
15
16
  const jira = new Jira(program);
16
17
 
17
18
  const project = await Project.pickProject(jira);
18
-
19
- const issueQuestions = [{
20
- type: 'list',
21
- name: 'issueType',
22
- message: 'Issue type:',
23
- choices: project.issueTypes,
24
- filter: name => project.issueTypes.find(obj => obj.name === name)
25
- }, {
26
- type: 'input',
27
- name: 'summary',
28
- message: 'Summary:',
29
- default: 'New Issue'
30
- }, {
31
- type: 'input',
32
- name: 'description',
33
- message: 'Description:'
34
- }, {
35
- type: 'confirm',
36
- name: 'assign',
37
- message: 'Do you want to assign it?'
38
- }, ];
39
-
40
- // Ask for the issue name and type
41
- const issueAnswers = await inquirer.prompt(issueQuestions);
19
+ const issueTypePos = await Ask.askList('Issue type:', project.issueTypes.map(issueType => issueType.name));
42
20
 
43
21
  // Create the issue object
44
22
  const newIssue = {
@@ -46,61 +24,23 @@ class Create extends Command {
46
24
  project: {
47
25
  key: project.key
48
26
  },
49
- summary: issueAnswers.summary,
27
+ summary: await Ask.askString('Summary:', 'New Issue'),
50
28
  issuetype: {
51
- id: issueAnswers.issueType.id
29
+ id: project.issueTypes[issueTypePos].id
52
30
  }
53
31
  }
54
32
  };
55
33
 
56
- if (issueAnswers.description) {
57
- newIssue.fields.description = issueAnswers.description;
58
- }
59
-
60
- if (issueAnswers.assign) {
61
- const userList = await User.pickUser(jira);
62
-
63
- const userNames = [];
64
- const userIds = [];
65
- userList.forEach(user => {
66
- if (user.active) {
67
- userNames.push(user.displayName);
68
- userIds.push(user.accountId);
69
- }
70
- });
71
-
72
- const assigneeQuestion = [{
73
- type: 'list',
74
- name: 'assignee',
75
- message: 'Assignee:',
76
- choices: userNames,
77
- filter: name => {
78
- const pos = userNames.indexOf(name);
79
- return {
80
- pos,
81
- name,
82
- id: userIds[pos]
83
- };
84
- }
85
- }];
86
-
87
- const assigneeAnswer = await inquirer.prompt(assigneeQuestion);
88
- newIssue.fields.assignee = {
89
- accountId: assigneeAnswer.assignee.id
90
- };
34
+ const description = await Ask.askString('Description:');
35
+ if (description) {
36
+ newIssue.fields.description = description;
91
37
  }
92
38
 
93
- if (issueAnswers.issueType.name === 'Task') {
94
- const parentIssueQuestion = [{
95
- type: 'input',
96
- name: 'issueParentName',
97
- message: 'Please provide the epic:'
98
- }];
99
-
100
- const parentIssueAnswer = await inquirer.prompt(parentIssueQuestion);
101
- if (parentIssueAnswer.issueParentName !== '') {
39
+ if (project.issueTypes[issueTypePos].name === 'Task') {
40
+ const parentIssue = await Ask.askString('Please provide the epic:');
41
+ if (parentIssue !== '') {
102
42
  newIssue.fields.parent = {
103
- key: parentIssueAnswer.issueParentName
43
+ key: parentIssue
104
44
  };
105
45
  }
106
46
  }
@@ -111,6 +51,21 @@ class Create extends Command {
111
51
  console.log('New issue: ' + color.bold.red(issue.key));
112
52
  console.log(color.blue(Issue.url(jira, issue.key)));
113
53
  console.log('');
54
+
55
+ if (await Ask.askBoolean('Do you want to assign it?')) {
56
+ await Set.assignIssue(jira, issue.key);
57
+ }
58
+
59
+ if (jira.fields && jira.fields.length > 0 &&
60
+ await Ask.askBoolean('Do you want to set custom fields?')) {
61
+ for (let fealdName of jira.fields) {
62
+ await Set.setCustomField(jira, filedName, issue.key);
63
+ }
64
+ }
65
+
66
+ if (await Ask.askBoolean('Do you want to set a status?')) {
67
+ await Set.setStatus(jira, issue.key);
68
+ }
114
69
  });
115
70
  }
116
71
  };
@@ -1,5 +1,3 @@
1
- import color from 'chalk';
2
-
3
1
  import Table from './table.js';
4
2
 
5
3
  class ErrorHandler {
@@ -8,7 +6,10 @@ class ErrorHandler {
8
6
  head: ['Errors']
9
7
  });
10
8
 
11
- e.error.errorMessages.forEach(error => table.addRow([color.blue(error)]));
9
+ e.error.errorMessages.forEach(error => table.addRow([{
10
+ color: "blue",
11
+ text: error
12
+ }]));
12
13
  console.log(table.toString());
13
14
  }
14
15
 
@@ -17,7 +18,10 @@ class ErrorHandler {
17
18
  head: ['Warnings']
18
19
  });
19
20
 
20
- messages.forEach(warning => table.addRow([color.blue(warning)]));
21
+ messages.forEach(warning => table.addRow([{
22
+ color: "blue",
23
+ text: warning
24
+ }]));
21
25
  console.log(table.toString());
22
26
  }
23
27
  };
package/src/field.js CHANGED
@@ -1,7 +1,5 @@
1
- import color from 'chalk';
2
-
1
+ import Ask from './ask.js';
3
2
  import Command from './command.js';
4
- import ErrorHandler from './errorhandler.js';
5
3
  import Jira from './jira.js';
6
4
  import Table from './table.js';
7
5
 
@@ -14,13 +12,7 @@ class Field extends Command {
14
12
  .action(async () => {
15
13
  const jira = new Jira(program);
16
14
 
17
- let resultFields;
18
- try {
19
- resultFields = await Field.listFields(jira);
20
- } catch (e) {
21
- ErrorHandler.showError(jira, e);
22
- return;
23
- }
15
+ const resultFields = await Field.listFields(jira);
24
16
 
25
17
  const table = new Table({
26
18
  head: ['Name', 'Supported', 'Type']
@@ -28,7 +20,10 @@ class Field extends Command {
28
20
 
29
21
  resultFields.forEach(field => {
30
22
  const supported = Field.isSupported(field.schema?.type);
31
- table.addRow([color.blue(field.name), supported, supported ? field.schema?.type : ""]);
23
+ table.addRow([{
24
+ color: "blue",
25
+ text: field.name
26
+ }, supported, supported ? field.schema?.type : ""]);
32
27
  });
33
28
  console.log(table.toString());
34
29
  });
@@ -39,13 +34,7 @@ class Field extends Command {
39
34
  .action(async fieldName => {
40
35
  const jira = new Jira(program);
41
36
 
42
- let resultFields;
43
- try {
44
- resultFields = await Field.listFields(jira);
45
- } catch (e) {
46
- ErrorHandler.showError(jira, e);
47
- return;
48
- }
37
+ const resultFields = await Field.listFields(jira);
49
38
 
50
39
  const fieldData = resultFields.find(field => field.name === fieldName);
51
40
  if (!fieldData) {
@@ -90,7 +79,10 @@ class Field extends Command {
90
79
  head: ['Name']
91
80
  });
92
81
 
93
- jira.fields.forEach(fieldName => table.addRow([color.blue(fieldName)]));
82
+ jira.fields.forEach(fieldName => table.addRow([{
83
+ color: "blue",
84
+ text: fieldName
85
+ }]));
94
86
  console.log(table.toString());
95
87
  });
96
88
  }
@@ -103,14 +95,8 @@ class Field extends Command {
103
95
  return ["string", "number"].includes(fieldType);
104
96
  }
105
97
 
106
- static async getFieldDataIfSupported(jira, fieldName) {
107
- let resultFields;
108
- try {
109
- resultFields = await Field.listFields(jira);
110
- } catch (e) {
111
- ErrorHandler.showError(jira, e);
112
- return null;
113
- }
98
+ static async askFieldIfSupported(jira, fieldName) {
99
+ const resultFields = await Field.listFields(jira);
114
100
 
115
101
  let fieldData;
116
102
  resultFields.forEach(field => {
@@ -130,17 +116,16 @@ class Field extends Command {
130
116
  let type;
131
117
  switch (fieldData.schema.type) {
132
118
  case 'number':
133
- type = 'number';
134
- break;
119
+ return {
120
+ value: await Ask.askNumber(`${fieldName}:`), key: fieldData.key
121
+ };
135
122
  case 'string':
136
- type = 'input';
137
- break;
123
+ return {
124
+ value: Ask.askString(`${fieldName}:`), key: fieldData.key
125
+ };
138
126
  }
139
127
 
140
- return {
141
- type,
142
- key: fieldData.key
143
- };
128
+ return null;
144
129
  }
145
130
  };
146
131
 
package/src/init.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import color from 'chalk';
2
- import inquirer from 'inquirer';
3
2
  import fs from 'fs';
4
3
 
4
+ import Ask from './ask.js';
5
5
  import Command from './command.js';
6
6
 
7
7
  class Init extends Command {
@@ -10,33 +10,13 @@ class Init extends Command {
10
10
  .description('Create the initial config file')
11
11
  .action(async () => {
12
12
  const opts = program.opts();
13
- const questions = [{
14
- type: ' input',
15
- name: 'host',
16
- message: 'Provide your jira host:',
17
- default: 'example.atlassian.net'
18
- }, {
19
- type: 'input',
20
- name: 'username',
21
- message: 'Please provide your jira username:'
22
- }, {
23
- type: 'password',
24
- name: 'password',
25
- message: 'API token:'
26
- }, {
27
- type: 'confirm',
28
- name: 'protocol',
29
- message: 'Enable HTTPS Protocol?'
30
- }];
31
-
32
- const answers = await inquirer.prompt(questions);
33
13
 
34
14
  const config = {
35
15
  jira: {
36
- protocol: answers.protocol ? 'https' : 'http',
37
- host: answers.host.trim(),
38
- username: answers.username.trim(),
39
- password: answers.password.trim(),
16
+ host: (await Ask.askString('Provide your jira host:', 'example.atlassian.net')).trim(),
17
+ protocol: await Ask.askBoolean('Enable HTTPS Protocol?') ? 'https' : 'http',
18
+ username: (await Ask.askString('Please provide your jira username:')).trim(),
19
+ password: (await Ask.askPassword('API token:')).trim(),
40
20
  apiVersion: '2',
41
21
  strictSSL: true,
42
22
  },
package/src/issue.js CHANGED
@@ -1,7 +1,4 @@
1
- import color from 'chalk';
2
-
3
1
  import Command from './command.js';
4
- import ErrorHandler from './errorhandler.js'
5
2
  import Field from './field.js';
6
3
  import Jira from './jira.js';
7
4
  import Table from './table.js';
@@ -21,22 +18,9 @@ class Issue extends Command {
21
18
  .action(async id => {
22
19
  const jira = new Jira(program);
23
20
 
24
- let resultFields;
25
- try {
26
- resultFields = await Field.listFields(jira);
27
- } catch (e) {
28
- ErrorHandler.showError(jira, e);
29
- return;
30
- }
31
-
32
- let result;
33
- try {
34
- result = await jira.spin('Running query...', jira.api.findIssue(id));
35
- } catch (e) {
36
- ErrorHandler.showError(jira, e);
37
- return;
38
- }
21
+ const resultFields = await Field.listFields(jira);
39
22
 
23
+ const result = await jira.spin('Running query...', jira.api.findIssue(id));
40
24
  const issue = Issue.replaceFields(result, resultFields);
41
25
 
42
26
  let epicIssue = null;
@@ -53,10 +37,16 @@ class Issue extends Command {
53
37
  'Summary', issue.fields['Summary'].trim()
54
38
  ],
55
39
  [
56
- 'URL', color.blue(Issue.url(jira, id))
40
+ 'URL', {
41
+ color: "blue",
42
+ text: Issue.url(jira, id)
43
+ },
57
44
  ],
58
45
  [
59
- 'Status', color.green(issue.fields['Status'].name)
46
+ 'Status', {
47
+ color: "green",
48
+ text: issue.fields['Status'].name
49
+ }
60
50
  ],
61
51
  [
62
52
  'Type', issue.fields['Issue Type'].name
@@ -74,13 +64,19 @@ class Issue extends Command {
74
64
  'Priority', issue.fields['Priority'].name
75
65
  ],
76
66
  [
77
- 'Epic Link', this.showEpicIssue(epicIssue)
67
+ 'Epic Link', {
68
+ color: "yellow",
69
+ text: this.showEpicIssue(epicIssue)
70
+ }
78
71
  ],
79
72
  [
80
73
  'Labels', issue.fields['Labels'].join(', ')
81
74
  ],
82
75
  [
83
- 'Sprint', issue.fields['Sprint']?.map(sprint => this.showSprint(sprint)).join(', ')
76
+ 'Sprint', {
77
+ color: "yellow",
78
+ text: issue.fields['Sprint']?.map(sprint => this.showSprint(sprint)).join(', ')
79
+ }
84
80
  ]
85
81
  ]);
86
82
 
@@ -117,7 +113,10 @@ class Issue extends Command {
117
113
  '', ''
118
114
  ],
119
115
  [
120
- 'Comment', color.yellow(comment.id)
116
+ 'Comment', {
117
+ color: "yellow",
118
+ text: comment.id
119
+ }
121
120
  ],
122
121
  [
123
122
  'Author', Issue.showUser(comment.author)
@@ -167,17 +166,17 @@ class Issue extends Command {
167
166
  static showUser(user) {
168
167
  if (!user) return "(null)";
169
168
  let str = user.displayName;
170
- if (user.emailAddress) str += ` (${color.yellow(user.emailAddress)})`;
169
+ if (user.emailAddress) str += ` (${user.emailAddress})`;
171
170
  return str;
172
171
  }
173
172
 
174
173
  showEpicIssue(issue) {
175
174
  if (!issue) return "";
176
- return `${color.blue(issue.key)} (${color.yellow(issue.fields['Summary'].trim())})`;
175
+ return `${issue.key} (${issue.fields['Summary'].trim()})`;
177
176
  }
178
177
 
179
178
  showSprint(sprint) {
180
- return `${color.blue(sprint.name)} (${color.yellow(sprint.state)})`;
179
+ return `${sprint.name} (${sprint.state})`;
181
180
  }
182
181
  };
183
182
 
package/src/jira.js CHANGED
@@ -2,6 +2,8 @@ import jiraClient from 'jira-client';
2
2
  import fs from 'fs';
3
3
  import ora from 'ora';
4
4
 
5
+ import ErrorHandler from './errorhandler.js'
6
+
5
7
  class Jira {
6
8
  constructor(program) {
7
9
  const opts = program.opts();
@@ -74,11 +76,12 @@ class Jira {
74
76
 
75
77
  try {
76
78
  const result = await promise;
79
+ spinner.stop();
77
80
  return result;
78
81
  } catch (e) {
79
- throw e;
80
- } finally {
81
82
  spinner.stop();
83
+ ErrorHandler.showError(this, e);
84
+ process.exit(1);
82
85
  }
83
86
  }
84
87
 
package/src/preset.js CHANGED
@@ -1,6 +1,3 @@
1
- import color from 'chalk';
2
- import inquirer from 'inquirer';
3
-
4
1
  import Command from './command.js';
5
2
  import Jira from './jira.js';
6
3
  import Table from './table.js';
@@ -47,9 +44,13 @@ class Preset extends Command {
47
44
  head: ['Name', 'Query']
48
45
  });
49
46
 
50
- Object.keys(jira.config.presets).forEach(key => table.addRow([color.blue(key),
51
- color.green(jira.config.presets[key])
52
- ]));
47
+ Object.keys(jira.config.presets).forEach(key => table.addRow([{
48
+ color: "blue",
49
+ text: key
50
+ }, {
51
+ color: "green",
52
+ text: jira.config.presets[key]
53
+ }, ]));
53
54
  console.log(table.toString());
54
55
  });
55
56
  }
package/src/project.js CHANGED
@@ -1,6 +1,4 @@
1
- import color from 'chalk';
2
- import inquirer from 'inquirer';
3
-
1
+ import Ask from './ask.js';
4
2
  import Command from './command.js';
5
3
  import Jira from './jira.js';
6
4
  import Table from './table.js';
@@ -20,7 +18,10 @@ class Project extends Command {
20
18
  head: ['Key', 'Name']
21
19
  });
22
20
 
23
- projects.forEach(project => table.addRow([color.blue(project.key), project.name]));
21
+ projects.forEach(project => table.addRow([{
22
+ color: "blue",
23
+ text: project.key
24
+ }, project.name]));
24
25
  console.log(table.toString());
25
26
  });
26
27
  }
@@ -41,39 +42,16 @@ class Project extends Command {
41
42
  return a.name > b.name;
42
43
  });
43
44
 
44
- const projectNames = [];
45
- const projectKeys = [];
46
- const issueTypes = [];
47
-
48
- meta.projects.forEach(project => {
49
- projectNames.push(project.name);
50
- projectKeys.push(project.key);
51
- issueTypes.push(project.issuetypes);
52
- });
53
-
54
- const projectQuestion = [{
55
- type: 'list',
56
- name: 'project',
57
- message: 'Project:',
58
- choices: projectNames,
59
- filter: name => {
60
- const pos = projectNames.indexOf(name);
61
- return {
62
- pos,
63
- name,
64
- key: projectKeys[pos]
65
- };
66
- }
67
- }];
68
-
69
- const projectAnswer = await inquirer.prompt(projectQuestion);
45
+ const projectPos = await Ask.askList('Project:', meta.projects.map(project => project.name));
46
+ const project = meta.projects[projectPos];
70
47
 
71
- jira.latestProject = projectAnswer.project.key
48
+ jira.latestProject = project.key;
72
49
  jira.syncConfig();
73
50
 
74
51
  return {
75
- issueTypes: issueTypes[projectAnswer.project.pos],
76
- ...projectAnswer.project
52
+ name: project.name,
53
+ key: project.key,
54
+ issueTypes: project.issuetypes,
77
55
  };
78
56
  }
79
57
  };
package/src/query.js CHANGED
@@ -1,5 +1,3 @@
1
- import color from 'chalk';
2
-
3
1
  import Command from './command.js';
4
2
  import ErrorHandler from './errorhandler.js';
5
3
  import Field from './field.js';
@@ -21,29 +19,17 @@ class Query extends Command {
21
19
  const jira = new Jira(program);
22
20
  const opts = cmd.opts();
23
21
 
24
- let resultFields;
25
- try {
26
- resultFields = await Field.listFields(jira);
27
- } catch (e) {
28
- ErrorHandler.showError(jira, e);
29
- return;
30
- }
22
+ const resultFields = await Field.listFields(jira);
31
23
 
32
24
  let expectedResult = opts.limit;
33
25
  let issues = [];
34
26
 
35
27
  while (issues.length < opts.limit) {
36
- let result;
37
- try {
38
- result = await jira.spin('Running query...',
39
- jira.api.searchJira(query, {
40
- startAt: issues.lengh,
41
- maxResults: opts.limit - issues.length
42
- }));
43
- } catch (e) {
44
- ErrorHandler.showError(jira, e);
45
- return;
46
- }
28
+ const result = await jira.spin('Running query...',
29
+ jira.api.searchJira(query, {
30
+ startAt: issues.lengh,
31
+ maxResults: opts.limit - issues.length
32
+ }));
47
33
 
48
34
  if (result.warningMessages) {
49
35
  ErrorHandler.showWarningMessages(result.warningMessages);
@@ -63,10 +49,19 @@ class Query extends Command {
63
49
  head: ['Key', 'Status', 'Type', 'Assignee', 'Summary']
64
50
  });
65
51
 
66
- issues.forEach(issue => table.addRow([color.blue(issue.key),
67
- color.green(issue.fields.status.name),
68
- color.green(issue.fields.issuetype.name),
69
- Issue.showUser(issue.fields.assignee),
52
+ issues.forEach(issue => table.addRow([{
53
+ color: "blue",
54
+ text: issue.key
55
+ }, {
56
+ color: "green",
57
+ text: issue.fields.status.name
58
+ }, {
59
+ color: "green",
60
+ text: issue.fields.issuetype.name
61
+ }, {
62
+ color: "yellow",
63
+ text: Issue.showUser(issue.fields.assignee)
64
+ },
70
65
  issue.fields.summary
71
66
  ]))
72
67
 
package/src/run.js CHANGED
@@ -1,5 +1,3 @@
1
- import color from 'chalk';
2
-
3
1
  import Command from './command.js';
4
2
  import ErrorHandler from './errorhandler.js';
5
3
  import Field from './field.js';
@@ -41,29 +39,17 @@ class Run extends Command {
41
39
  return;
42
40
  }
43
41
 
44
- let resultFields;
45
- try {
46
- resultFields = await Field.listFields(jira);
47
- } catch (e) {
48
- ErrorHandler.showError(jira, e);
49
- return;
50
- }
42
+ const resultFields = await Field.listFields(jira);
51
43
 
52
44
  let expectedResult = opts.limit;
53
45
  let issues = [];
54
46
 
55
47
  while (issues.length < opts.limit) {
56
- let result;
57
- try {
58
- result = await jira.spin('Running query...',
59
- jira.api.searchJira(query, {
60
- startAt: issues.lengh,
61
- maxResults: opts.limit - issues.length
62
- }));
63
- } catch (e) {
64
- ErrorHandler.showError(jira, e);
65
- return;
66
- }
48
+ const result = await jira.spin('Running query...',
49
+ jira.api.searchJira(query, {
50
+ startAt: issues.lengh,
51
+ maxResults: opts.limit - issues.length
52
+ }));
67
53
 
68
54
  if (result.warningMessages) {
69
55
  ErrorHandler.showWarningMessages(result.warningMessages);
package/src/set.js CHANGED
@@ -1,9 +1,7 @@
1
- import inquirer from 'inquirer';
2
-
1
+ import Ask from './ask.js';
3
2
  import Command from './command.js';
4
3
  import Field from './field.js';
5
4
  import Jira from './jira.js';
6
- import ErrorHandler from './errorhandler.js';
7
5
  import User from './user.js';
8
6
 
9
7
  class Set extends Command {
@@ -15,46 +13,7 @@ class Set extends Command {
15
13
  .argument('<id>', 'The issue ID')
16
14
  .action(async id => {
17
15
  const jira = new Jira(program);
18
-
19
- const userList = await User.pickUser(jira);
20
- const userNames = [];
21
- const userIds = [];
22
- userList.forEach(user => {
23
- if (user.active) {
24
- userNames.push(user.displayName);
25
- userIds.push(user.accountId);
26
- }
27
- });
28
-
29
- const assigneeQuestion = [{
30
- type: 'list',
31
- name: 'assignee',
32
- message: 'Assignee:',
33
- choices: userNames,
34
- filter: name => {
35
- const pos = userNames.indexOf(name);
36
- return {
37
- pos,
38
- name,
39
- id: userIds[pos]
40
- };
41
- }
42
- }];
43
-
44
- const assigneeAnswer = await inquirer.prompt(assigneeQuestion);
45
- const issue = {
46
- fields: {
47
- assignee: {
48
- accountId: assigneeAnswer.assignee.id
49
- }
50
- }
51
- }
52
-
53
- try {
54
- await jira.spin('Updating the issue...', jira.api.updateIssue(id, issue));
55
- } catch (e) {
56
- ErrorHandler.showError(jira, e);
57
- }
16
+ await Set.assignIssue(jira, id);
58
17
  });
59
18
 
60
19
  setCmd.command('status')
@@ -62,42 +21,7 @@ class Set extends Command {
62
21
  .argument('<id>', 'The issue ID')
63
22
  .action(async id => {
64
23
  const jira = new Jira(program);
65
-
66
- const transitionList = await jira.spin('Retrieving transitions...', jira.api.listTransitions(id));
67
- const transitionNames = [];
68
- const transitionIds = [];
69
- transitionList.transitions.forEach(transition => {
70
- transitionNames.push(transition.name);
71
- transitionIds.push(transition.id);
72
- });
73
-
74
- const transitionQuestion = [{
75
- type: 'list',
76
- name: 'transition',
77
- message: 'Status:',
78
- choices: transitionNames,
79
- filter: name => {
80
- const pos = transitionNames.indexOf(name);
81
- return {
82
- pos,
83
- name,
84
- id: transitionIds[pos]
85
- };
86
- }
87
- }];
88
-
89
- const transitionAnswer = await inquirer.prompt(transitionQuestion);
90
-
91
- const transition = {
92
- transition: {
93
- id: transitionAnswer.transition.id
94
- }
95
- };
96
- try {
97
- await jira.spin('Updating the issue...', jira.api.transitionIssue(id, transition));
98
- } catch (e) {
99
- ErrorHandler.showError(jira, e);
100
- }
24
+ await Set.setStatus(jira, id);
101
25
  });
102
26
 
103
27
  setCmd.command('custom')
@@ -106,34 +30,53 @@ class Set extends Command {
106
30
  .argument('<id>', 'The issue ID')
107
31
  .action(async (fieldName, id) => {
108
32
  const jira = new Jira(program);
33
+ await Set.setCustomField(jira, fieldName, id);
34
+ });
35
+ }
36
+
37
+ static async assignIssue(jira, id) {
38
+ const userList = await User.pickUser(jira);
39
+ const activeUsers = userList.filter(user => user.active);
40
+ const assignee = await Ask.askList('Assignee:', activeUsers.map(user => user.displayName));
109
41
 
110
- const fieldData = await Field.getFieldDataIfSupported(jira, fieldName);
111
- if (!fieldData) {
112
- console.log("Unsupported field type");
113
- return;
42
+ const issue = {
43
+ fields: {
44
+ assignee: {
45
+ accountId: activeUsers[assignee].accountId
114
46
  }
47
+ }
48
+ }
115
49
 
116
- const question = [{
117
- type: fieldData.type,
118
- name: 'value',
119
- message: `${fieldName}:`,
120
- }];
50
+ await jira.spin('Updating the issue...', jira.api.updateIssue(id, issue));
51
+ }
121
52
 
122
- const answer = await inquirer.prompt(question);
53
+ static async setCustomField(jira, fieldName, id) {
54
+ const field = await Field.askFieldIfSupported(jira, fieldName);
55
+ if (!field) {
56
+ console.log("Unsupported field type");
57
+ return;
58
+ }
59
+
60
+ const data = {};
61
+ data[field.key] = field.value;
62
+
63
+ await jira.spin('Updating the issue...', jira.api.updateIssue(id, {
64
+ fields: {
65
+ ...data
66
+ }
67
+ }));
68
+ }
123
69
 
124
- const data = {};
125
- data[fieldData.key] = answer.value;
70
+ static async setStatus(jira, id) {
71
+ const transitionList = await jira.spin('Retrieving transitions...', jira.api.listTransitions(id));
72
+ const transitionPos = await Ask.askList('Status:', transitionList.transitions.map(transition => transition.name));
73
+ const transition = {
74
+ transition: {
75
+ id: transitionList.transitions[transitionPos].id
76
+ }
77
+ };
126
78
 
127
- try {
128
- await jira.spin('Updating the issue...', jira.api.updateIssue(id, {
129
- fields: {
130
- ...data
131
- }
132
- }));
133
- } catch (e) {
134
- ErrorHandler.showError(jira, e);
135
- }
136
- });
79
+ await jira.spin('Updating the issue...', jira.api.transitionIssue(id, transition));
137
80
  }
138
81
  };
139
82
 
package/src/sprint.js CHANGED
@@ -1,8 +1,6 @@
1
- import inquirer from 'inquirer';
2
-
1
+ import Ask from './ask.js';
3
2
  import Command from './command.js';
4
3
  import Jira from './jira.js';
5
- import ErrorHandler from './errorhandler.js';
6
4
  import Project from './project.js';
7
5
 
8
6
  class Sprint extends Command {
@@ -21,18 +19,14 @@ class Sprint extends Command {
21
19
  return;
22
20
  }
23
21
 
24
- try {
25
- await jira.spin('Adding the issue to the sprint...',
26
- jira.apiAgileRequest(`/sprint/${sprintId}/issue`, {
27
- method: 'POST',
28
- followAllRedirects: true,
29
- body: {
30
- issues: [id]
31
- }
32
- }));
33
- } catch (e) {
34
- ErrorHandler.showError(jira, e);
35
- }
22
+ await jira.spin('Adding the issue to the sprint...',
23
+ jira.apiAgileRequest(`/sprint/${sprintId}/issue`, {
24
+ method: 'POST',
25
+ followAllRedirects: true,
26
+ body: {
27
+ issues: [id]
28
+ }
29
+ }));
36
30
  });
37
31
 
38
32
  sprintCmd.command('remove')
@@ -41,18 +35,14 @@ class Sprint extends Command {
41
35
  .action(async id => {
42
36
  const jira = new Jira(program);
43
37
 
44
- try {
45
- await jira.spin('Adding the issue to the sprint...',
46
- jira.apiAgileRequest("/backlog/issue", {
47
- method: 'POST',
48
- followAllRedirects: true,
49
- body: {
50
- issues: [id]
51
- }
52
- }));
53
- } catch (e) {
54
- ErrorHandler.showError(jira, e);
55
- }
38
+ await jira.spin('Adding the issue to the sprint...',
39
+ jira.apiAgileRequest("/backlog/issue", {
40
+ method: 'POST',
41
+ followAllRedirects: true,
42
+ body: {
43
+ issues: [id]
44
+ }
45
+ }));
56
46
  });
57
47
  }
58
48
 
@@ -62,71 +52,23 @@ class Sprint extends Command {
62
52
  jira.api.getAllBoards(undefined, undefined, undefined, undefined,
63
53
  project.key));
64
54
 
65
- const boardNames = [];
66
- const boardIds = [];
67
-
68
- boardList.values.forEach(board => {
69
- boardNames.push(board.name);
70
- boardIds.push(board.id);
71
- });
72
-
73
- const boardQuestion = [{
74
- type: 'list',
75
- name: 'board',
76
- message: 'Board:',
77
- choices: boardNames,
78
- filter: name => {
79
- const pos = boardNames.indexOf(name);
80
- return {
81
- pos,
82
- name,
83
- id: boardIds[pos]
84
- };
85
- }
86
- }];
87
-
88
- const boardAnswer = await inquirer.prompt(boardQuestion);
55
+ const boardPos = await Ask.askList('Board:', boardList.values.map(board => board.name));
89
56
 
90
57
  const sprintList = await jira.spin('Retrieving sprints...',
91
- jira.api.getAllSprints(boardAnswer.board.id));
92
-
93
- const sprintNames = [];
94
- const sprintIds = [];
58
+ jira.api.getAllSprints(boardList.values[boardPos].id));
95
59
 
96
- sprintList.values.forEach(sprint => {
97
- if (sprint.state === 'active' || sprint.state === 'future') {
98
- sprintNames.push(sprint.name);
99
- sprintIds.push(sprint.id);
100
- }
101
- });
60
+ const sprints = sprintList.values.filter(sprint => sprint.state === 'active' || sprint.state === 'future');
102
61
 
103
- if (sprintNames.length === 0) {
62
+ if (sprints.length === 0) {
104
63
  return 0;
105
64
  }
106
65
 
107
- let sprintId = sprintIds[0];
108
-
109
- if (sprintNames.length > 1) {
110
- const sprintQuestion = [{
111
- type: 'list',
112
- name: 'sprint',
113
- message: 'Board:',
114
- choices: sprintNames,
115
- filter: name => {
116
- const pos = sprintNames.indexOf(name);
117
- return {
118
- pos,
119
- name,
120
- id: sprintIds[pos]
121
- };
122
- }
123
- }];
124
-
125
- const sprintAnswer = await inquirer.prompt(sprintQuestion);
126
- sprintId = sprintAnswer.sprint.id;
66
+ if (sprints.length > 1) {
67
+ const sprintPos = await Ask.askList('Sprint:', sprints.map(sprint => sprint.name));
68
+ return sprints[sprintPos].id;
127
69
  }
128
70
 
129
- return sprintId;
71
+ return sprints[0].id;
130
72
  }
131
73
  };
132
74
 
package/src/table.js CHANGED
@@ -1,7 +1,5 @@
1
1
  import color from 'chalk';
2
2
 
3
- const REGEXP_ASCII = /\u001b\[(?:\d*;){0,5}\d*m/g;
4
-
5
3
  class Table {
6
4
  constructor(options) {
7
5
  this._columns = [];
@@ -17,9 +15,15 @@ class Table {
17
15
  this._columns.push(this._createColumn(undefined, this._rows));
18
16
  }
19
17
 
20
- row.forEach((field, pos) => this._columns[pos].rows.push(("" + field).split("\n")));
18
+ row.forEach((field, pos) => {
19
+ if (typeof field !== "object") field = {
20
+ text: field
21
+ };
22
+ field.text = ("" + field.text).split("\n");
23
+ this._columns[pos].rows.push(field);
24
+ });
21
25
 
22
- for (let i = row.length; i < this._columns.length; ++i) this._columns[i].rows.push("");
26
+ for (let i = row.length; i < this._columns.length; ++i) this._columns[i].rows.push({});
23
27
 
24
28
  ++this._rows;
25
29
  }
@@ -50,7 +54,7 @@ class Table {
50
54
  const rowHeight = Math.max(...this._columns.map(column => this._computeRowHeight(column, row)));
51
55
 
52
56
  for (let i = 0; i < rowHeight; ++i) {
53
- lines.push(this._columns.map(column => this._toWidth(this._computeLine(column, row, i), column.width)).join(" "));
57
+ lines.push(this._columns.map(column => this._colorize(column.rows[row], this._toWidth(this._computeLine(column.rows[row], i), column.width))).join(" "));
54
58
  }
55
59
  }
56
60
 
@@ -67,30 +71,30 @@ class Table {
67
71
 
68
72
  _computeColumnWidth(column) {
69
73
  column.width = Math.max(...column.rows.map(row =>
70
- Math.max(...row.map(line => line.replace(REGEXP_ASCII, "").length))
74
+ Math.max(...row.text.map(line => line.length))
71
75
  ));
72
76
 
73
77
  if (column.head) column.width = Math.max(column.width, column.head.length);
74
78
  }
75
79
 
76
80
  _computeRowHeight(column, row) {
77
- return column.rows[row].length;
81
+ return column.rows[row].text.length;
78
82
  }
79
83
 
80
84
  _toWidth(str, width) {
81
85
  str = str || "";
82
86
 
83
- let strLength = str.replace(REGEXP_ASCII, "").length;
87
+ let strLength = str.length;
84
88
  if (strLength > width) {
85
89
  return this._truncate(str, width - 1) + "…";
86
90
  }
87
91
 
88
- for (let strLength = str.replace(REGEXP_ASCII, "").length; strLength < width; ++strLength) str += " ";
92
+ for (let strLength = str.length; strLength < width; ++strLength) str += " ";
89
93
  return str;
90
94
  }
91
95
 
92
- _computeLine(column, row, subRow) {
93
- return column.rows[row].length < subRow ? "" : column.rows[row][subRow];
96
+ _computeLine(row, subRow) {
97
+ return row.text.length < subRow ? "" : row.text[subRow];
94
98
  }
95
99
 
96
100
  _resizeWidthOf(size) {
@@ -101,10 +105,10 @@ class Table {
101
105
  this._columns.forEach(column => {
102
106
  column.rows.forEach((row, pos) => {
103
107
  let lines = [];
104
- row.forEach(line => {
108
+ row.text.forEach(line => {
105
109
  lines = lines.concat(this._maybeSplitRow(line, column.width));
106
110
  });
107
- column.rows[pos] = lines;
111
+ column.rows[pos].text = lines;
108
112
  });
109
113
  });
110
114
  }
@@ -143,24 +147,15 @@ class Table {
143
147
  }
144
148
 
145
149
  _truncate(str, width) {
146
- let out = "";
147
-
148
- while (true) {
149
- const firstAscii = /\u001b\[((?:\d*;){0,5}\d*)m/g.exec(str);
150
- if (!firstAscii) {
151
- out += str.slice(0, width);
152
- break;
153
- }
154
-
155
- let p = str.slice(0, firstAscii.index);
156
- p = p.slice(0, width);
157
- width -= p.length;
158
- out += p + firstAscii[0];
150
+ return str.slice(0, width);
151
+ }
159
152
 
160
- str = str.slice(firstAscii[0].length + firstAscii.index);
153
+ _colorize(row, text) {
154
+ if (!("color" in row)) {
155
+ return text;
161
156
  }
162
157
 
163
- return out;
158
+ return color[row.color].apply(null, [text]);
164
159
  }
165
160
  };
166
161