Skip to content
This repository has been archived by the owner on Nov 27, 2023. It is now read-only.

Commit

Permalink
feat: hover issue
Browse files Browse the repository at this point in the history
Show issue and comments on hover

Closes #241
  • Loading branch information
KnisterPeter committed Oct 19, 2017
1 parent 27764bf commit ae9606c
Show file tree
Hide file tree
Showing 11 changed files with 411 additions and 227 deletions.
438 changes: 225 additions & 213 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@
},
"devDependencies": {
"@knisterpeter/standard-tslint": "^1.5.0",
"@types/common-tags": "1.4.0",
"@types/lru-cache": "^4.1.0",
"@types/mocha": "^2.2.40",
"@types/node": "^8.0.0",
Expand All @@ -231,6 +232,7 @@
"vscode": "1.1.6"
},
"dependencies": {
"common-tags": "1.4.0",
"conventional-changelog-lint-config-angular": "1.0.0",
"execa": "^0.8.0",
"lru-cache": "^4.1.1",
Expand Down
49 changes: 46 additions & 3 deletions src/issues.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import { stripIndents } from 'common-tags';
import { component, inject, initialize } from 'tsdi';
import * as vscode from 'vscode';
import { WorkflowManager } from './workflow-manager';

@component
export class HoverProvider implements vscode.DocumentLinkProvider {
export class HoverProvider implements vscode.DocumentLinkProvider, vscode.HoverProvider {

@inject('vscode.ExtensionContext')
private context: vscode.ExtensionContext;

@inject
private workflowManager: WorkflowManager;

private hoverContent: {[target: string]: string} = {};

@initialize
protected init(): void {
this.context.subscriptions.push(vscode.languages.registerDocumentLinkProvider('*', this));
this.context.subscriptions.push(
vscode.languages.registerDocumentLinkProvider('*', this),
vscode.languages.registerHoverProvider('*', this)
);
vscode.window.onDidChangeActiveTextEditor(() => this.hoverContent = {});
}

public async provideDocumentLinks(document: vscode.TextDocument)
Expand Down Expand Up @@ -42,7 +49,7 @@ export class HoverProvider implements vscode.DocumentLinkProvider {
new vscode.Position(lineNo, match.index),
new vscode.Position(lineNo, match.index + match[0].length)
);
const url = await this.workflowManager.getIssueUrl(uri, match[0]);
const url = await this.workflowManager.getIssueUrl(uri, match[0].substr(1));
if (url) {
matches.push({
range,
Expand All @@ -52,4 +59,40 @@ export class HoverProvider implements vscode.DocumentLinkProvider {
}
return matches;
}

public async provideHover(document: vscode.TextDocument, position: vscode.Position)
: Promise<vscode.Hover | undefined> {
const folder = vscode.workspace.getWorkspaceFolder(document.uri);
if (!folder) {
return undefined;
}
const links = await this.provideDocumentLinks(document);
const link = links.find(link => link.range.contains(position));
if (!link || !link.target) {
return undefined;
}
const target = link.target.toString();
if (this.hoverContent[target]) {
return new vscode.Hover(this.hoverContent[target], link.range);
}
const issues = await this.workflowManager.issues(folder.uri);
const issue = issues.find(issue => issue.url === target);
if (!issue) {
return undefined;
}
const comments = await this.workflowManager.getIssueComments(issue);
const content = stripIndents`
## ${issue.title}
${issue.body}
---
${comments.map(comment => comment.body).join('\n\n---\n\n')}
`;
this.hoverContent[target] = content;
return new vscode.Hover(content, link.range);
}

}
13 changes: 13 additions & 0 deletions src/provider/github/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export interface GitHub {
getUser(username: string): Promise<GitHubResponse<UserResponse>>;

listAssignees(owner: string, repo: string): Promise<GitHubResponse<UserResponse[]>>;

getIssueComments(owner: string, repo: string, number: number): Promise<GitHubResponse<IssueComment[]>>;
}

export interface GitHubResponse<T> {
Expand All @@ -45,6 +47,11 @@ export interface GitHubResponse<T> {
body: T;
}

export interface IssueComment {
body: string;
user: UserResponse;
}

export interface UpdatePullRequestBody {
title?: string;
body?: string;
Expand Down Expand Up @@ -78,6 +85,7 @@ export interface Issue {
number: number;
state: 'open';
title: string;
body: string;
pull_request?: object;
}

Expand Down Expand Up @@ -254,6 +262,7 @@ namespace impl {
}

export class GitHubBlueprint implements GitHub {

@Headers('Accept: application/vnd.github.polaris-preview')
@Get('/repos/:owner/:repo')
public getRepository(): any {/* */}
Expand Down Expand Up @@ -303,6 +312,10 @@ namespace impl {

@Get('/repos/:owner/:repo/assignees')
public listAssignees(): any {/* */}

@Get('/repos/:owner/:repo/issues/:number/comments')
public getIssueComments(): any {/* */}

}

}
48 changes: 48 additions & 0 deletions src/provider/github/issue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Response } from '../client';
import { Issue, IssueComment } from '../issue';
import { GitHub, Issue as IssueStruct } from './index';
import { GithubRepository } from './repository';
import { GithubUser } from './user';

export class GithubIssue implements Issue {

private client: GitHub;
private repository: GithubRepository;
private struct: IssueStruct;

public get number(): number {
return this.struct.number;
}

public get title(): string {
return this.struct.title;
}

public get url(): string {
return this.struct.html_url;
}

public get body(): string {
return this.struct.body;
}

constructor(client: GitHub, repository: GithubRepository, struct: IssueStruct) {
this.client = client;
this.repository = repository;
this.struct = struct;
}

public async comments(): Promise<Response<IssueComment[]>> {
const response = await this.client.getIssueComments(
this.repository.owner,
this.repository.repository,
this.number
);
return {
body: response.body.map(comment => ({
body: comment.body,
user: new GithubUser(this.client, comment.user)
}))
};
}
}
7 changes: 2 additions & 5 deletions src/provider/github/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
IssuesParameters
} from '../repository';
import { GitHub, GithubRepositoryStruct } from './index';
import { GithubIssue } from './issue';
import { GithubPullRequest } from './pull-request';
import { GithubUser } from './user';

Expand Down Expand Up @@ -117,11 +118,7 @@ export class GithubRepository implements Repository {
return {
body: response.body
.filter(issue => !Boolean(issue.pull_request))
.map(issue => ({
number: issue.number,
title: issue.title,
url: issue.html_url
}))
.map(issue => new GithubIssue(this.client, this, issue))
};
}

Expand Down
10 changes: 10 additions & 0 deletions src/provider/gitlab/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface GitLab {
: Promise<GitLabResponse<AcceptMergeRequestResponse>>;
getProjectIssues(id: string, body: ProjectIssuesBody): Promise<GitLabResponse<Issue[]>>;
searchUser(parameters?: SearchUsersParameters): Promise<GitLabResponse<UserResponse[]>>;
getIssueNotes(id: string, issue_iid: number): Promise<GitLabResponse<IssueNote[]>>;
}

export interface GitLabResponse<T> {
Expand All @@ -26,6 +27,11 @@ export interface GitLabResponse<T> {
body: T;
}

export interface IssueNote {
body: string;
author: UserResponse;
}

export interface AcceptMergeRequestBody {
should_remove_source_branch?: boolean;
}
Expand Down Expand Up @@ -55,6 +61,7 @@ export interface Issue {
iid: number;
title: string;
web_url: string;
description: string;
}

export interface CreateMergeRequestBody {
Expand Down Expand Up @@ -208,6 +215,9 @@ namespace impl {
@Get('/projects/:id/issues')
public getProjectIssues(): any {/* */}

@Get('/projects/:id/issues/:issue_iid/notes')
public getIssueNotes(): any {/* */}

}

}
47 changes: 47 additions & 0 deletions src/provider/gitlab/issue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Response } from '../client';
import { Issue, IssueComment } from '../issue';
import { GitLab, Issue as IssueStruct } from './api';
import { GitLabRepository } from './repository';
import { GitLabUser } from './user';

export class GitLabIssue implements Issue {

private client: GitLab;
private repository: GitLabRepository;
private struct: IssueStruct;

public get number(): number {
return this.struct.iid;
}

public get title(): string {
return this.struct.title;
}

public get url(): string {
return this.struct.web_url;
}

public get body(): string {
return this.struct.description;
}

constructor(client: GitLab, repository: GitLabRepository, struct: IssueStruct) {
this.client = client;
this.repository = repository;
this.struct = struct;
}

public async comments(): Promise<Response<IssueComment[]>> {
const response = await this.client.getIssueNotes(
encodeURIComponent(this.repository.pathWithNamespace),
this.number
);
return {
body: response.body.map(note => ({
body: note.body,
user: new GitLabUser(this.client, note.author)
}))
};
}
}
7 changes: 2 additions & 5 deletions src/provider/gitlab/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
CreateMergeRequestBody,
ProjectIssuesBody
} from './api';
import { GitLabIssue } from './issue';
import { GitLabMergeRequest } from './merge-request';
import { GitLabUser } from './user';

Expand Down Expand Up @@ -172,11 +173,7 @@ export class GitLabRepository implements Repository {
body
);
return {
body: response.body.map(issue => ({
number: issue.iid,
title: issue.title,
url: issue.web_url
}))
body: response.body.map(issue => new GitLabIssue(this.client, this, issue))
};
}

Expand Down
11 changes: 11 additions & 0 deletions src/provider/issue.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
import { Response } from './client';
import { User } from './user';

export interface Issue {
number: number;
title: string;
url: string;
body: string;

comments(): Promise<Response<IssueComment[]>>;
}

export interface IssueComment {
user: User;
body: string;
}
6 changes: 5 additions & 1 deletion src/workflow-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as vscode from 'vscode';

import { Git } from './git';
import { createClient, Client } from './provider/client';
import { Issue } from './provider/issue';
import { Issue, IssueComment } from './provider/issue';
import { PullRequest, MergeBody, MergeMethod, Comment } from './provider/pull-request';
import { Repository, ListPullRequestsParameters, CreatePullRequestBody } from './provider/repository';
import { User } from './provider/user';
Expand Down Expand Up @@ -308,4 +308,8 @@ export class WorkflowManager {
return (await pullRequest.getComments()).body;
}

public async getIssueComments(issue: Issue): Promise<IssueComment[]> {
return (await issue.comments()).body;
}

}

0 comments on commit ae9606c

Please sign in to comment.