Skip to content

Commit 25b5e03

Browse files
authored
Merge pull request #3 from KnisterPeter/fix-status
fix: update status async
2 parents 0be57a4 + f8bde29 commit 25b5e03

File tree

11 files changed

+84
-62
lines changed

11 files changed

+84
-62
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,7 @@ This vscode extension integrates with JIRA.
1717
Store your project setup in `.vscode/settings.json` and add the keys `jira.baseUrl` and `jira.projectNames`.
1818

1919
Then setup your credentials first by running `Setup credentials...` command.
20+
21+
# Resources
22+
23+
Based on [JIRA APIs](https://docs.atlassian.com/jira/REST/)

src/api.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Pretend, Get, Post, Interceptor, IPretendRequestInterceptor, IPretendDe
33
export interface Jira {
44
serverInfo(): Promise<ServerInfo>;
55
search(params: {jql: string}): Promise<Issues>;
6+
getIssue(issue: string): Promise<Issue>;
67
getTransitions(issue: string): Promise<Transitions>;
78
doTransition(issue: string, body: DoTransitionBody): Promise<void>;
89
}
@@ -91,6 +92,8 @@ namespace impl {
9192
public serverInfo(): any {/* */}
9293
@Post('/rest/api/2/search')
9394
public search(): any {/* */}
95+
@Get('/rest/api/2/issue/:issue')
96+
public getIssue(): any {/* */}
9497
@Get('/rest/api/2/issue/:issue/transitions')
9598
public getTransitions(): any {/* */}
9699
@Post('/rest/api/2/issue/:issue/transitions')

src/commands/activate-issue.ts

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as vscode from 'vscode';
33

44
import { Issue } from '../api';
55
import { Command } from '../command';
6-
import state, { ActiveIssue } from '../state';
6+
import state, { ActiveIssue, getActiveIssue, setActiveIssue } from '../state';
77

88
export class ActivateIssueCommand implements Command {
99

@@ -12,30 +12,18 @@ export class ActivateIssueCommand implements Command {
1212
@bind
1313
public async run(preselected: Issue | null): Promise<void> {
1414
const issue = await this.selectIssue(preselected);
15-
if (issue !== undefined && state.workspaceState) {
16-
const activeIssue: ActiveIssue = {
17-
key: issue ? issue.key : undefined,
18-
status: issue ? issue.fields.status.name : undefined
19-
};
20-
state.workspaceState.update('vscode-jira:active-issue', activeIssue);
21-
state.update();
15+
if (issue !== undefined) {
16+
setActiveIssue(issue);
2217
}
2318
}
2419

2520
private async selectIssue(preselected: Issue | null): Promise<Issue | null | undefined> {
2621
if (preselected || preselected === null) {
2722
return preselected;
2823
}
29-
const activateIssue = this.getActiveIssue();
30-
const name = activateIssue && activateIssue.key
31-
? `Deactivate ${activateIssue.key}`
32-
: undefined;
24+
const activateIssue = getActiveIssue();
25+
const name = activateIssue ? `Deactivate ${activateIssue.key}` : undefined;
3326
return await vscode.commands.executeCommand<Issue | undefined | null>('vscode-jira.listMyIssues', name);
3427
}
3528

36-
private getActiveIssue(): ActiveIssue | undefined {
37-
if (state.workspaceState) {
38-
return state.workspaceState.get('vscode-jira:active-issue');
39-
}
40-
}
4129
}

src/commands/browse-my-issues.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export class BrowseMyIssuesCommand implements Command {
1616

1717
@bind
1818
public async run(): Promise<void> {
19-
const issue = await vscode.commands.executeCommand<Issue | undefined>('vscode-jira.listMyIssues', false);
19+
const issue = await vscode.commands.executeCommand<Issue | undefined>('vscode-jira.listMyIssues');
2020
if (issue) {
2121
const url = `${this.baseUrl}/browse/${issue.key}`;
2222
await vscode.commands.executeCommand('vscode.open', vscode.Uri.parse(url));

src/commands/list-my-issues.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,29 @@ import * as vscode from 'vscode';
33

44
import { Issue } from '../api';
55
import { Command } from '../command';
6+
import { checkEnabled } from '../extension';
67
import state from '../state';
78

89
export class ListMyIssuesCommand implements Command<Issue | undefined | null> {
910

1011
public id = 'vscode-jira.listMyIssues';
1112

12-
private baseUrl: string | undefined;
13+
private baseUrl: string;
1314

14-
private projectNames: string[] | undefined;
15+
private projectNames: string[];
1516

1617
constructor(baseUrl: string | undefined, projectNames: string[] | undefined) {
17-
this.baseUrl = baseUrl;
18-
this.projectNames = projectNames;
18+
if (baseUrl) {
19+
this.baseUrl = baseUrl;
20+
}
21+
if (projectNames) {
22+
this.projectNames = projectNames;
23+
}
1924
}
2025

2126
@bind
22-
public async run(withEmpty: string): Promise<Issue | undefined | null> {
23-
if (!state.jira || !this.baseUrl || !this.projectNames) {
24-
vscode.window.showInformationMessage(
25-
'No JIRA client configured. Setup baseUrl, projectNames, username and password');
27+
public async run(withEmpty?: string): Promise<Issue | undefined | null> {
28+
if (!checkEnabled()) {
2629
return;
2730
}
2831
const issues = await state.jira.search({
@@ -53,6 +56,7 @@ export class ListMyIssuesCommand implements Command<Issue | undefined | null> {
5356
if (selected) {
5457
return selected.issue;
5558
}
59+
return undefined;
5660
}
5761

5862
}

src/commands/setup-credentials.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export class SetupCredentialsCommand implements Command {
4141
}
4242
await this.context.globalState.update(`vscode-jira:${this.baseUrl}`,
4343
`${username}${CREDENTIALS_SEPARATOR}${password}`);
44-
state.jira = await connectToJira();
44+
state.jira = (await connectToJira())!;
4545
state.update();
4646
}
4747

src/commands/transition-issue.ts

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,20 @@ import * as vscode from 'vscode';
33

44
import { Issue, Transition } from '../api';
55
import { Command } from '../command';
6-
import state, { ActiveIssue } from '../state';
6+
import { checkEnabled } from '../extension';
7+
import state, { ActiveIssue, getActiveIssue } from '../state';
78

89
export class TransitionIssueCommand implements Command {
910

1011
public id = 'vscode-jira.transitionIssues';
1112

1213
@bind
1314
public async run(withDeactivation = true): Promise<void> {
14-
if (!state.jira) {
15-
vscode.window.showInformationMessage(
16-
'No JIRA client configured. Setup baseUrl, projectNames, username and password');
15+
if (!checkEnabled()) {
1716
return;
1817
}
19-
const activeIssue = this.getActiveIssue();
20-
if (activeIssue && activeIssue.key) {
18+
const activeIssue = getActiveIssue();
19+
if (activeIssue) {
2120
const selected = await this.selectTransition(withDeactivation, activeIssue);
2221
if (selected === null) {
2322
await vscode.commands.executeCommand('vscode-jira.activateIssues', null);
@@ -35,9 +34,6 @@ export class TransitionIssueCommand implements Command {
3534

3635
private async selectTransition(withActivation: boolean, activeIssue: ActiveIssue):
3736
Promise<Transition | null | undefined> {
38-
if (!state.jira || !activeIssue.key) {
39-
return;
40-
}
4137
const transitions = await state.jira.getTransitions(activeIssue.key);
4238
const picks = transitions.transitions.map(transition => ({
4339
label: transition.to.name || transition.name,
@@ -64,16 +60,7 @@ export class TransitionIssueCommand implements Command {
6460
return `Deactivate ${activeIssue.key}`;
6561
}
6662

67-
private getActiveIssue(): ActiveIssue | undefined {
68-
if (state.workspaceState) {
69-
return state.workspaceState.get('vscode-jira:active-issue');
70-
}
71-
}
72-
7363
private async deactivateWhenDone(activeIssue: ActiveIssue): Promise<void> {
74-
if (!state.jira || !activeIssue.key) {
75-
return;
76-
}
7764
const result = await state.jira.search({jql: `issue = "${activeIssue.key}" AND resolution = Resolved`});
7865
if (result.issues.length > 0) {
7966
vscode.commands.executeCommand('vscode-jira.activateIssues', null);

src/extension.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function activate(_context: vscode.ExtensionContext): void {
3333
if (credentials) {
3434
const connect = async() => {
3535
const [username, password] = credentials.split(CREDENTIALS_SEPARATOR);
36-
state.jira = await connectToJira();
36+
state.jira = (await connectToJira())!;
3737
state.update();
3838
};
3939
connect().catch(() => {
@@ -54,6 +54,16 @@ export function activate(_context: vscode.ExtensionContext): void {
5454
context.subscriptions.push(new StatusBarManager());
5555
}
5656

57+
export function checkEnabled(): boolean {
58+
const config = vscode.workspace.getConfiguration('jira');
59+
if (!state.jira || !config.has('baseUrl') || !config.has('projectNames')) {
60+
vscode.window.showInformationMessage(
61+
'No JIRA client configured. Setup baseUrl, projectNames, username and password');
62+
return false;
63+
}
64+
return true;
65+
}
66+
5767
export async function connectToJira(): Promise<Jira | undefined> {
5868
const credentials: string | undefined = context.globalState.get(`vscode-jira:${baseUrl}`);
5969
if (credentials && baseUrl) {
@@ -67,4 +77,5 @@ export async function connectToJira(): Promise<Jira | undefined> {
6777
}
6878
return client;
6979
}
80+
return undefined;
7081
}

src/state.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,42 @@
11
import * as vscode from 'vscode';
2-
import { Jira } from './api';
2+
import { Jira, Issue } from './api';
33

44
export interface State {
5-
jira?: Jira;
5+
jira: Jira;
66
workspaceState?: vscode.Memento;
77
subscriber: (() => void)[];
88
update(): void;
99
}
1010

1111
export interface ActiveIssue {
12-
key?: string;
13-
status?: string;
12+
key: string;
1413
}
1514

1615
const state: State = {
16+
jira: undefined as any,
1717
subscriber: [],
1818
update(): void {
1919
this.subscriber.forEach(subscriber => subscriber());
2020
}
2121
};
2222

2323
export default state;
24+
25+
export function getActiveIssue(): ActiveIssue | undefined {
26+
if (state.workspaceState) {
27+
return state.workspaceState.get('vscode-jira:active-issue');
28+
}
29+
return undefined;
30+
}
31+
32+
export function setActiveIssue(issue: Issue | null): void {
33+
if (state.workspaceState) {
34+
state.workspaceState.update('vscode-jira:active-issue', issue
35+
? {
36+
key: issue.key
37+
}
38+
: undefined
39+
);
40+
state.update();
41+
}
42+
}

src/status-bar.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
11
import * as vscode from 'vscode';
22

3-
import state, { ActiveIssue } from './state';
3+
import state, { ActiveIssue, getActiveIssue } from './state';
44

55
export class StatusBarManager {
66

77
private item: vscode.StatusBarItem;
88

9+
private interval: NodeJS.Timer;
10+
911
constructor() {
1012
this.item = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0);
1113
this.item.text = '$(issue-opened)';
1214
state.subscriber.push(() => {
1315
this.updateStatus();
1416
});
17+
this.interval = setInterval(() => {
18+
this.updateStatus();
19+
}, 1000 * 60 * 5);
1520
}
1621

17-
public updateStatus(): void {
22+
private async updateStatus(): Promise<void> {
1823
this.item.show();
19-
const activeIssue = this.getActiveIssue();
20-
if (activeIssue && activeIssue.key) {
21-
this.item.text = `$(issue-opened) ${activeIssue.key} ${activeIssue.status}`;
24+
const activeIssue = getActiveIssue();
25+
if (activeIssue) {
26+
const issue = await state.jira.getIssue(activeIssue.key);
27+
this.item.text = `$(issue-opened) ${activeIssue.key} ${issue.fields.status.name}`;
2228
this.item.tooltip = 'Click to transition issue...';
2329
this.item.command = 'vscode-jira.transitionIssues';
2430
} else {
@@ -28,13 +34,8 @@ export class StatusBarManager {
2834
}
2935
}
3036

31-
private getActiveIssue(): ActiveIssue | undefined {
32-
if (state.workspaceState) {
33-
return state.workspaceState.get('vscode-jira:active-issue');
34-
}
35-
}
36-
3737
public dispose(): void {
3838
this.item.dispose();
39+
clearInterval(this.interval);
3940
}
4041
}

0 commit comments

Comments
 (0)