Skip to content

Commit

Permalink
Merge branch 'create_ticket'
Browse files Browse the repository at this point in the history
  • Loading branch information
gioboa committed Nov 19, 2018
2 parents c80ea80 + fa4642d commit d2c9c18
Show file tree
Hide file tree
Showing 11 changed files with 398 additions and 24 deletions.
Binary file added images/icons/dark/plus_nav.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/icons/light/plus_nav.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@
"light": "images/icons/light/refresh.svg",
"dark": "images/icons/dark/refresh.svg"
}
},
{
"command": "jira-plugin.createIssueCommand",
"title": "Create issue",
"icon": {
"light": "images/icons/light/plus_nav.png",
"dark": "images/icons/dark/plus_nav.png"
}
}
],
"menus": {
Expand Down Expand Up @@ -210,6 +218,11 @@
"command": "jira-plugin.refresh",
"when": "view == jiraExplorer",
"group": "navigation"
},
{
"command": "jira-plugin.createIssueCommand",
"when": "view == jiraExplorer",
"group": "navigation"
}
],
"view/item/context": [
Expand Down
4 changes: 2 additions & 2 deletions src/commands/change-issue-assignee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ export class ChangeIssueAssigneeCommand implements Command {
let issue = issueItem.issue;
// verify if it's the current working issue
if (!isWorkingIssue(issue.key)) {
let assignee = await selectAssignee(false, false);
let assignee = await selectAssignee(false, false, true, undefined);
if (!!assignee) {
// call Jira API
const res = await state.jira.setAssignIssue({ issueKey: issue.key, assignee: assignee });
const res = await state.jira.setAssignIssue({ issueKey: issue.key, assignee: <string>assignee });
await vscode.commands.executeCommand('jira-plugin.refresh');
}
}
Expand Down
60 changes: 60 additions & 0 deletions src/commands/create-issue.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { IAssignee, IIssueType, IPriority } from '../http/api.model';

// statuses for new issue loop
export const NEW_ISSUE_STATUS = {
STOP: -1,
CONTINUE: 0,
INSERT: 1
};

export interface INewIssue {
type: IIssueType | undefined;
summary: string | undefined;
description: string | undefined;
assignee: IAssignee | string | undefined;
priority: IPriority | undefined;
}

// items available inside the selector
export const NEW_ISSUE_FIELDS = {
TYPE: {
field: 'type',
label: 'Type * :',
description: 'Select type'
},
SUMMARY: {
field: 'summary',
label: 'Summary * :',
description: 'Insert summary'
},
DESCRIPTION: {
field: 'description',
label: 'Description * :',
description: 'Insert description'
},
ASSIGNEE: {
field: 'assignee',
label: 'Assignee :',
description: 'Select assignee'
},
PRIORITY: {
field: 'priority',
label: 'Priority :',
description: 'Select priority'
},
DIVIDER: {
field: 'divider',
label: '--- * required ---',
description: ''
},
INSERT_ISSUE: {
field: 'insert_issue',
label: 'Insert issue',
description: ''
},
EXIT: {
field: 'exit',
label: 'Exit',
description: ''
}
};
201 changes: 201 additions & 0 deletions src/commands/create-issue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import * as vscode from 'vscode';
import { IssueItem } from '../explorer/item/issue-item';
import { IAssignee, ICreateIssue, IIssueType, IPriority } from '../http/api.model';
import { getConfigurationByKey } from '../shared/configuration';
import { CONFIG, MAX_RESULTS } from '../shared/constants';
import { selectAssignee, selectIssueType } from '../shared/select-utilities';
import state, { printErrorMessageInOutput, verifyCurrentProject } from '../state/state';
import { INewIssue, NEW_ISSUE_FIELDS, NEW_ISSUE_STATUS } from './create-issue.model';
import { OpenIssueCommand } from './open-issue';
import { Command } from './shared/command';

export class CreateIssueCommand implements Command {
public id = 'jira-plugin.createIssueCommand';

public async run(issueItem: IssueItem): Promise<void> {
const project = getConfigurationByKey(CONFIG.WORKING_PROJECT) || '';
if (verifyCurrentProject(project)) {
try {
// load once the options
const assignees = await state.jira.getAssignees({ project, maxResults: MAX_RESULTS });
const priorities = await state.jira.getAllPriorities();
const types = await state.jira.getAllIssueTypes();

// instance for keep data
const newIssue: INewIssue = {
type: undefined,
summary: undefined,
description: undefined,
assignee: undefined,
priority: undefined
};
let status = NEW_ISSUE_STATUS.CONTINUE;
while (status === NEW_ISSUE_STATUS.CONTINUE) {
// genearte/update new issue selector
const createIssuePicks = generateNewIssuePicks(newIssue, priorities && priorities.length > 0);
const selected = await vscode.window.showQuickPick(createIssuePicks, {
placeHolder: `Insert Jira issue`,
matchOnDescription: true
});

// manage the selected field
if (!!selected && selected.field !== NEW_ISSUE_FIELDS.DIVIDER.field) {
if (selected.field !== NEW_ISSUE_FIELDS.INSERT_ISSUE.field && selected.field !== NEW_ISSUE_FIELDS.EXIT.field) {
await manageSelectedField(selected, newIssue, types, assignees, priorities);
} else {
if (mandatoryFieldsOk(newIssue)) {
status = selected.field === NEW_ISSUE_FIELDS.INSERT_ISSUE.field ? NEW_ISSUE_STATUS.INSERT : NEW_ISSUE_STATUS.STOP;
}
}
}
}
// insert
if (status === NEW_ISSUE_STATUS.INSERT) {
await insertNewTicket(newIssue);
} else {
// console.log(`Exit`);
}
} catch (err) {
printErrorMessageInOutput(err);
}
}
}
}

const generateNewIssuePicks = (newIssue: INewIssue, addPriority: boolean) => {
const picks = [
{
field: NEW_ISSUE_FIELDS.TYPE.field,
label: NEW_ISSUE_FIELDS.TYPE.label,
description: !!newIssue.type ? newIssue.type.name : NEW_ISSUE_FIELDS.TYPE.description
},
{
field: NEW_ISSUE_FIELDS.SUMMARY.field,
label: NEW_ISSUE_FIELDS.SUMMARY.label,
description: newIssue.summary || NEW_ISSUE_FIELDS.SUMMARY.description
},
{
field: NEW_ISSUE_FIELDS.DESCRIPTION.field,
label: NEW_ISSUE_FIELDS.DESCRIPTION.label,
description: newIssue.description || NEW_ISSUE_FIELDS.DESCRIPTION.description
},
{
field: NEW_ISSUE_FIELDS.ASSIGNEE.field,
label: NEW_ISSUE_FIELDS.ASSIGNEE.label,
description: !!newIssue.assignee ? (<IAssignee>newIssue.assignee).name : NEW_ISSUE_FIELDS.ASSIGNEE.description
},
{
field: NEW_ISSUE_FIELDS.DIVIDER.field,
label: NEW_ISSUE_FIELDS.DIVIDER.label,
description: NEW_ISSUE_FIELDS.DIVIDER.description
},
{
field: NEW_ISSUE_FIELDS.INSERT_ISSUE.field,
label: NEW_ISSUE_FIELDS.INSERT_ISSUE.label,
description: NEW_ISSUE_FIELDS.INSERT_ISSUE.description
},
{
field: NEW_ISSUE_FIELDS.EXIT.field,
label: NEW_ISSUE_FIELDS.EXIT.label,
description: NEW_ISSUE_FIELDS.EXIT.description
}
];

if (addPriority) {
picks.splice(4, 0, {
field: NEW_ISSUE_FIELDS.PRIORITY.field,
label: NEW_ISSUE_FIELDS.PRIORITY.label,
description: !!newIssue.priority ? newIssue.priority.name : NEW_ISSUE_FIELDS.PRIORITY.description
});
}
return picks;
};

const mandatoryFieldsOk = (newIssue: INewIssue) => {
return !!newIssue.summary && !!newIssue.description && !!newIssue.type;
};

const insertNewTicket = async (newIssue: INewIssue) => {
const project = getConfigurationByKey(CONFIG.WORKING_PROJECT);
if (mandatoryFieldsOk(newIssue)) {
let request = {
fields: {
project: {
key: project
},
summary: newIssue.summary,
description: newIssue.description,
issuetype: {
id: (<IIssueType>newIssue.type).id
}
}
} as ICreateIssue;
// adding assignee
if (!!newIssue.assignee) {
request.fields = {
...request.fields,
assignee: {
key: (<IAssignee>newIssue.assignee).key
}
};
}
// adding priority
if (!!newIssue.priority) {
request.fields = {
...request.fields,
priority: {
id: newIssue.priority.id
}
};
}
const createdIssue = await state.jira.createIssue(request);
if (!!createdIssue && !!createdIssue.key) {
// if the response is ok, we will open the created issue
const action = await vscode.window.showInformationMessage('Issue created', 'Open in browser');
if (action === 'Open in browser') {
new OpenIssueCommand().run(createdIssue.key);
}
}
}
};

const manageSelectedField = async (
selected: any,
newIssue: INewIssue,
types: IIssueType[],
assignees: IAssignee[],
priorities: IPriority[]
) => {
switch (selected.field) {
case NEW_ISSUE_FIELDS.SUMMARY.field:
case NEW_ISSUE_FIELDS.DESCRIPTION.field:
(<any>newIssue)[selected.field] = await vscode.window.showInputBox({
ignoreFocusOut: true,
placeHolder: ''
});
break;
case NEW_ISSUE_FIELDS.TYPE.field:
newIssue.type = await selectIssueType(true, types);
break;
case NEW_ISSUE_FIELDS.ASSIGNEE.field:
newIssue.assignee = await selectAssignee(false, false, false, assignees);
break;
case NEW_ISSUE_FIELDS.PRIORITY.field:
{
const priorityPicks = (priorities || []).map((priority: IPriority) => {
return {
pickValue: priority,
label: priority.id,
description: priority.name
};
});
const selected = await vscode.window.showQuickPick(priorityPicks, {
matchOnDescription: true,
matchOnDetail: true,
placeHolder: 'Select an issue'
});
newIssue.priority = selected ? selected.pickValue : undefined;
}
break;
}
};
2 changes: 1 addition & 1 deletion src/commands/issue-add-comment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class IssueAddCommentCommand implements Command {
// ask for assignee if there is one or more [@] in the comment
const num = (text.match(new RegExp('[@]', 'g')) || []).length;
for (let i = 0; i < num; i++) {
const assignee = await selectAssignee(false, false);
const assignee = await selectAssignee(false, false, true, undefined);
if (!!assignee) {
text = text.replace('[@]', `[~${assignee}]`);
} else {
Expand Down
18 changes: 13 additions & 5 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import * as vscode from 'vscode';
import { ChangeIssueAssigneeCommand } from './commands/change-issue-assignee';
import { ChangeIssueStatusCommand } from './commands/change-issue-status';
import { CreateIssueCommand } from './commands/create-issue';
import { IssueAddCommentCommand } from './commands/issue-add-comment';
import { IssueAddWorklogCommand } from './commands/issue-add-worklog';
import { OpenGitHubRepoCommand } from './commands/open-github-repo';
import { OpenIssueCommand } from './commands/open-issue';
import { SetWorkingIssueCommand } from './commands/set-working-issue';
import { SetWorkingProjectCommand } from './commands/set-working-project';
Expand All @@ -13,7 +15,6 @@ import { IssueLinkProvider } from './shared/document-link-provider';
import { selectIssue } from './shared/select-utilities';
import { StatusBarManager } from './shared/status-bar';
import state, { connectToJira } from './state/state';
import { OpenGitHubRepoCommand } from './commands/open-github-repo';

let channel: vscode.OutputChannel;

Expand Down Expand Up @@ -42,15 +43,22 @@ export const activate = async (context: vscode.ExtensionContext): Promise<void>
new OpenGitHubRepoCommand(),
new OpenIssueCommand(),
new SetWorkingIssueCommand(),
new IssueAddWorklogCommand()
new IssueAddWorklogCommand(),
new CreateIssueCommand()
];

// register all commands
context.subscriptions.push(vscode.commands.registerCommand('jira-plugin.refresh', () => selectIssue(SEARCH_MODE.REFRESH)));
context.subscriptions.push(vscode.commands.registerCommand('jira-plugin.allIssuesCommand', () => selectIssue(SEARCH_MODE.ALL)));
context.subscriptions.push(vscode.commands.registerCommand('jira-plugin.currentSprintCommand', () => selectIssue(SEARCH_MODE.CURRENT_SPRINT)));
context.subscriptions.push(vscode.commands.registerCommand('jira-plugin.myIssuesByStatusCommand', () => selectIssue(SEARCH_MODE.MY_STATUS)));
context.subscriptions.push(vscode.commands.registerCommand('jira-plugin.issuesByStatusAssigneeCommand', () => selectIssue(SEARCH_MODE.STATUS_ASSIGNEE)));
context.subscriptions.push(
vscode.commands.registerCommand('jira-plugin.currentSprintCommand', () => selectIssue(SEARCH_MODE.CURRENT_SPRINT))
);
context.subscriptions.push(
vscode.commands.registerCommand('jira-plugin.myIssuesByStatusCommand', () => selectIssue(SEARCH_MODE.MY_STATUS))
);
context.subscriptions.push(
vscode.commands.registerCommand('jira-plugin.issuesByStatusAssigneeCommand', () => selectIssue(SEARCH_MODE.STATUS_ASSIGNEE))
);
context.subscriptions.push(vscode.commands.registerCommand('jira-plugin.issuesByStatusCommand', () => selectIssue(SEARCH_MODE.STATUS)));
context.subscriptions.push(vscode.commands.registerCommand('jira-plugin.issueByIdCommand', () => selectIssue(SEARCH_MODE.ID)));
context.subscriptions.push(vscode.commands.registerCommand('jira-plugin.issuesBySummaryCommand', () => selectIssue(SEARCH_MODE.SUMMARY)));
Expand Down
Loading

0 comments on commit d2c9c18

Please sign in to comment.