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 +1 -1
- package/src/ask.js +57 -0
- package/src/comment.js +1 -3
- package/src/create.js +27 -72
- package/src/errorhandler.js +8 -4
- package/src/field.js +20 -35
- package/src/init.js +5 -25
- package/src/issue.js +25 -26
- package/src/jira.js +5 -2
- package/src/preset.js +7 -6
- package/src/project.js +11 -33
- package/src/query.js +19 -24
- package/src/run.js +6 -20
- package/src/set.js +44 -101
- package/src/sprint.js +25 -83
- package/src/table.js +23 -28
package/package.json
CHANGED
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
|
-
|
|
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:
|
|
27
|
+
summary: await Ask.askString('Summary:', 'New Issue'),
|
|
50
28
|
issuetype: {
|
|
51
|
-
id:
|
|
29
|
+
id: project.issueTypes[issueTypePos].id
|
|
52
30
|
}
|
|
53
31
|
}
|
|
54
32
|
};
|
|
55
33
|
|
|
56
|
-
|
|
57
|
-
|
|
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 (
|
|
94
|
-
const
|
|
95
|
-
|
|
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:
|
|
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
|
};
|
package/src/errorhandler.js
CHANGED
|
@@ -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([
|
|
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([
|
|
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
|
|
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
|
-
|
|
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([
|
|
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
|
-
|
|
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([
|
|
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
|
|
107
|
-
|
|
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
|
-
|
|
134
|
-
|
|
119
|
+
return {
|
|
120
|
+
value: await Ask.askNumber(`${fieldName}:`), key: fieldData.key
|
|
121
|
+
};
|
|
135
122
|
case 'string':
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
username:
|
|
39
|
-
password:
|
|
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
|
-
|
|
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',
|
|
40
|
+
'URL', {
|
|
41
|
+
color: "blue",
|
|
42
|
+
text: Issue.url(jira, id)
|
|
43
|
+
},
|
|
57
44
|
],
|
|
58
45
|
[
|
|
59
|
-
'Status',
|
|
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',
|
|
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',
|
|
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',
|
|
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 += ` (${
|
|
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 `${
|
|
175
|
+
return `${issue.key} (${issue.fields['Summary'].trim()})`;
|
|
177
176
|
}
|
|
178
177
|
|
|
179
178
|
showSprint(sprint) {
|
|
180
|
-
return `${
|
|
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([
|
|
51
|
-
color
|
|
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
|
|
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([
|
|
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
|
|
45
|
-
const
|
|
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 =
|
|
48
|
+
jira.latestProject = project.key;
|
|
72
49
|
jira.syncConfig();
|
|
73
50
|
|
|
74
51
|
return {
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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([
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
42
|
+
const issue = {
|
|
43
|
+
fields: {
|
|
44
|
+
assignee: {
|
|
45
|
+
accountId: activeUsers[assignee].accountId
|
|
114
46
|
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
115
49
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
name: 'value',
|
|
119
|
-
message: `${fieldName}:`,
|
|
120
|
-
}];
|
|
50
|
+
await jira.spin('Updating the issue...', jira.api.updateIssue(id, issue));
|
|
51
|
+
}
|
|
121
52
|
|
|
122
|
-
|
|
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
|
-
|
|
125
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
|
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(
|
|
92
|
-
|
|
93
|
-
const sprintNames = [];
|
|
94
|
-
const sprintIds = [];
|
|
58
|
+
jira.api.getAllSprints(boardList.values[boardPos].id));
|
|
95
59
|
|
|
96
|
-
sprintList.values.
|
|
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 (
|
|
62
|
+
if (sprints.length === 0) {
|
|
104
63
|
return 0;
|
|
105
64
|
}
|
|
106
65
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
|
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) =>
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
92
|
+
for (let strLength = str.length; strLength < width; ++strLength) str += " ";
|
|
89
93
|
return str;
|
|
90
94
|
}
|
|
91
95
|
|
|
92
|
-
_computeLine(
|
|
93
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
153
|
+
_colorize(row, text) {
|
|
154
|
+
if (!("color" in row)) {
|
|
155
|
+
return text;
|
|
161
156
|
}
|
|
162
157
|
|
|
163
|
-
return
|
|
158
|
+
return color[row.color].apply(null, [text]);
|
|
164
159
|
}
|
|
165
160
|
};
|
|
166
161
|
|