From 420303bffab45250344089006dfc1d9f6dc4be82 Mon Sep 17 00:00:00 2001 From: ljoonal Date: Thu, 4 Jul 2019 15:45:46 +0300 Subject: [PATCH 1/2] Use .vscode folder for settings and such --- README.md | 14 +- package-lock.json | 12 +- package.json | 219 +++++++++++++++----------- src/Config.ts | 82 ++++++++++ src/configurationProvider.ts | 32 ---- src/extension.ts | 109 ++++--------- src/issue.ts | 107 +++++++------ src/issueProvider.ts | 287 ++++++++++++++++++----------------- 8 files changed, 456 insertions(+), 406 deletions(-) create mode 100644 src/Config.ts delete mode 100644 src/configurationProvider.ts diff --git a/README.md b/README.md index a25d8c7..f3411f2 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,13 @@ Issuetracker for Gitea ## Getting Started -To setup a gitea issue tracked project you need to first select the issues tab at the activitiy bar. After that open the command palette in order to type in the command `Initialize Gitea-Issue Tracker` and enter your crendentials: +Go to your settings, and find the `Gitea` section, and fill out the details. + +Please make sure to not to make your authtoken public, as it can be used to act on your behalf. +You can store it in the user settings, whilst leaving the rest in the workspace settings. + +### The following details are needed + - Authtoken - Domain in format: "example.com" - Repository Owner (may be an organisation): "TestOrganisation" @@ -16,8 +22,10 @@ When you've finished you can press the refresh button in the open issues section ![Issues with multiple colors](./media/gitea-issues.png) -In order to get nice looking issue icons in multiple colors (of your choice) you just need to assign a label to your issue. The color is being fetched automatically. If you change the color of the label however, you need to delete the `.gitea/{issuename}.svg` file in the given folder. If you skip this step, the file is not going to get updated. In most cases you need to restart visual studio code to apply the icons in the issues tab. +In order to get nice looking issue icons in multiple colors (of your choice) you just need to assign a label to your issue. The color is being fetched automatically. In most cases you need to restart visual studio code to apply the icons in the issues tab if you've changed them though. + ## Future + - Implement a `Close Issue` Button - Create Issues via Webview -- `Comment` Issues \ No newline at end of file +- `Comment` Issues diff --git a/package-lock.json b/package-lock.json index c0d5b66..3a3dabf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -251,14 +251,6 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "configparser": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/configparser/-/configparser-0.3.6.tgz", - "integrity": "sha512-qCYjKDEK69qRtm3n+RYM55b8XiH2uKfnI6qOKg+ZLrKSG5vY59RBcZhLxxVd18+B5C5Zc7Jy8KpFsB5YOAD+hw==", - "requires": { - "mkdirp": "^0.5.1" - } - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -606,12 +598,14 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, "requires": { "minimist": "0.0.8" } diff --git a/package.json b/package.json index 8080f54..0a48a2b 100644 --- a/package.json +++ b/package.json @@ -1,93 +1,128 @@ { - "name": "gitea-vscode", - "displayName": "Gitea-VSCode", - "description": "Gitea Issue Tracker for vs-code", - "publisher": "IJustDev", - "version": "0.0.6", - "engines": { - "vscode": "^1.32.0" - }, - "categories": [ - "Other" - ], - "activationEvents": [ - "onView:open-issues", - "onCommand:giteaIssues.initRepo", - "onCommand:giteaIssues.refreshIssues" - ], - "main": "./out/extension.js", - "contributes": { - "viewsContainers": { - "activitybar": [ - { - "id": "issue-explorer", - "title": "Gitea-Issues", - "icon": "media/issue.svg" - } - ] - }, - "views": { - "issue-explorer": [ - { - "id": "open-issues", - "name": "Open Issues" - }, - { - "id": "closed-issues", - "name": "Closed Issues" - } - ] - }, - "commands": [ - { - "command": "giteaIssues.openIssue", - "title": "Show" - }, - { - "command": "giteaIssues.refreshIssues", - "title": "Refresh", - "icon": { - "dark": "resources/dark/refresh.svg", - "light": "resources/light/refresh.svg" - } - }, - { - "command": "giteaIssues.initRepo", - "title": "Initialize Gitea-Issue Tracker" - } - ], - "menus": { - "view/title": [ - { - "command": "giteaIssues.refreshIssues", - "group": "navigation", - "when": "view == open-issues" - } - ] - } - }, - "scripts": { - "vscode:prepublish": "npm run compile", - "compile": "tsc -p ./", - "watch": "tsc -watch -p ./", - "postinstall": "node ./node_modules/vscode/bin/install", - "test": "npm run compile && node ./node_modules/vscode/bin/test" - }, - "devDependencies": { - "@types/axios": "^0.14.0", - "@types/mocha": "^2.2.42", - "@types/node": "^10.12.21", - "tslint": "^5.12.1", - "typescript": "^3.3.1", - "vscode": "^1.1.28" - }, - "dependencies": { - "axios": "^0.18.1", - "configparser": "^0.3.6", - "marked": "^0.6.2" - }, - "repository": { - "type": "github", - "url": "https://github.com/IJustdev/Gitea-VSCode.git" - } -} \ No newline at end of file + "name": "gitea-vscode", + "displayName": "Gitea-VSCode", + "description": "Gitea Issue Tracker for vs-code", + "publisher": "IJustDev", + "version": "0.0.7", + "engines": { + "vscode": "^1.32.0" + }, + "categories": [ + "Other" + ], + "activationEvents": [ + "onView:open-issues", + "onCommand:giteaIssues.initRepo", + "onCommand:giteaIssues.refreshIssues" + ], + "main": "./out/extension.js", + "contributes": { + "viewsContainers": { + "activitybar": [ + { + "id": "issue-explorer", + "title": "Gitea-Issues", + "icon": "media/issue.svg" + } + ] + }, + "views": { + "issue-explorer": [ + { + "id": "open-issues", + "name": "Open Issues" + }, + { + "id": "closed-issues", + "name": "Closed Issues" + } + ] + }, + "commands": [ + { + "command": "giteaIssues.openIssue", + "title": "Show" + }, + { + "command": "giteaIssues.refreshIssues", + "title": "Refresh", + "icon": { + "dark": "resources/dark/refresh.svg", + "light": "resources/light/refresh.svg" + } + }, + { + "command": "giteaIssues.initRepo", + "title": "Initialize Gitea-Issue Tracker" + } + ], + "menus": { + "view/title": [ + { + "command": "giteaIssues.refreshIssues", + "group": "navigation", + "when": "view == open-issues" + } + ] + }, + "configuration": { + "title": "Gitea", + "properties": { + "gitea.token": { + "scope": "application", + "type": "string", + "default": "", + "description": "The token for the gitea server." + }, + "gitea.domain": { + "scope": "resource", + "type": "string", + "default": "", + "description": "The remote gitea instance's domain." + }, + "gitea.owner": { + "scope": "resource", + "type": "string", + "default": "", + "description": "The username for the repository." + }, + "gitea.repo": { + "scope": "resource", + "type": "string", + "default": "", + "description": "The repository name." + }, + "gitea.ssl": { + "scope": "resource", + "type": "boolean", + "default": true, + "description": "If https should be used or not." + } + } + } + }, + "scripts": { + "vscode:prepublish": "npm run compile", + "compile": "tsc -p ./", + "watch": "tsc -watch -p ./", + "postinstall": "node ./node_modules/vscode/bin/install", + "test": "npm run compile && node ./node_modules/vscode/bin/test" + }, + "devDependencies": { + "@types/axios": "^0.14.0", + "@types/mocha": "^2.2.42", + "@types/node": "^10.12.21", + "tslint": "^5.12.1", + "typescript": "^3.3.1", + "vscode": "^1.1.28" + }, + "dependencies": { + "axios": "^0.18.1", + "marked": "^0.6.2" + }, + "repository": { + "type": "github", + "url": "https://github.com/IJustdev/Gitea-VSCode.git" + }, + "license": "MIT" +} diff --git a/src/Config.ts b/src/Config.ts new file mode 100644 index 0000000..cb90d8e --- /dev/null +++ b/src/Config.ts @@ -0,0 +1,82 @@ +import { workspace, window } from 'vscode'; + +interface ConfigStorage { + token: string; + domain: string; + owner: string; + repo: string; + ssl: boolean; +} + +export interface ConfigTypes extends ConfigStorage { + readonly repoApiUrl: string; +} + +export class Config implements ConfigTypes { + private get storage() { + return workspace.getConfiguration('gitea', null); + } + + private loadConfigValue(configKey: T, type: 'string' | 'boolean' | 'number', acceptDetault = false): ConfigStorage[T] { + if (!acceptDetault && !this.storage.has(configKey)) { + window.showErrorMessage("Gitea-VSCode didn't find a required configuration value: " + configKey); + throw new Error(`Failed to load configuration: "${configKey}"`); + } + + const value = this.storage.has(configKey) + ? (this.storage.get(configKey) as ConfigStorage[T]) + : (this.storage.inspect(configKey) as { defaultValue: ConfigStorage[T]; key: string }).defaultValue; + + if (typeof value === type && (type !== 'string' || (value as string).length > 0)) { + return value as ConfigStorage[T]; + } + + window.showErrorMessage('Gitea-VSCode failed to load a configuration value that is needed: ' + configKey); + throw new Error(`Failed to load configuration: "gitea.${configKey}"`); + } + + public get token() { + return this.loadConfigValue('token', 'string'); + } + + public set token(value) { + this.storage.update('token', value); + } + + public get domain() { + return this.loadConfigValue('domain', 'string'); + } + + public set domain(value) { + this.storage.update('domain', value); + } + + public get owner() { + return this.loadConfigValue('owner', 'string'); + } + + public set owner(value) { + this.storage.update('owner', value); + } + + public get repo() { + return this.loadConfigValue('repo', 'string'); + } + + public set repo(value) { + this.storage.update('repo', value); + } + + public get ssl() { + return this.loadConfigValue('ssl', 'boolean', true); + } + + public set ssl(value) { + this.storage.update('ssl', value); + } + + public get repoApiUrl() { + const prefix = this.ssl ? 'https' : 'http'; + return prefix + '://' + this.domain + '/api/v1/repos/' + this.owner + '/' + this.repo + '/issues'; + } +} diff --git a/src/configurationProvider.ts b/src/configurationProvider.ts deleted file mode 100644 index b36409a..0000000 --- a/src/configurationProvider.ts +++ /dev/null @@ -1,32 +0,0 @@ -const ConfigParser = require("configparser"); -const path = require("path"); - -export class RepositoryInformationManager { - public token(rootPath: string | undefined) { - const config = new ConfigParser(); - config.read(path.join(rootPath as string, "/.gitea/config.ini")); - return config.get("PRIVATE", "token"); - } - public repoApiUrl(rootPath: string | undefined) { - const config = new ConfigParser(); - config.read(rootPath + "/.gitea/config.ini"); - const domain = config.get("REPO", "domain"); - const repo_owner = config.get("REPO", "repo_owner"); - const repo_name = config.get("REPO", "repo_name"); - const ssl = config.get("REPO", "ssl"); - const prefix = ssl ? "https" : "http"; - return prefix + "://" + domain + "/api/v1/repos/" + repo_owner + "/" + repo_name + "/issues"; - } - public saveRepoInformation(rootPath: string | undefined, repoInformations: any) { - const file_path = path.join(rootPath as string, ".gitea/config.ini"); - const config = new ConfigParser(); - config.addSection("PRIVATE"); - config.addSection("REPO"); - config.set("PRIVATE", "token", repoInformations.token); - config.set("REPO", "domain", repoInformations.domain); - config.set("REPO", "repo_owner", repoInformations.repo_owner); - config.set("REPO", "repo_name", repoInformations.repo_name); - config.set("REPO", "ssl", true); - config.write(file_path, true); - } -} diff --git a/src/extension.ts b/src/extension.ts index e1a698a..ff6c16c 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,90 +1,47 @@ import * as vscode from 'vscode'; import { showIssueHTML } from './template.html'; -import { Issue } from "./issue"; -import { RepositoryInformationManager } from './configurationProvider'; +import { Issue } from './issue'; import { OpenIssuesProvider, ClosedIssuesProvider } from './issueProvider'; export function activate(context: vscode.ExtensionContext) { - let disposable = vscode.commands.registerCommand('giteaIssues.initRepo', () => { - initializeIssueTracker(); - }); - context.subscriptions.push(disposable); - let openIssues: Array = []; - const openIssuesProvider = new OpenIssuesProvider(); - const closedIssuesProvider = new ClosedIssuesProvider(); + let openIssues: Array = []; + const openIssuesProvider = new OpenIssuesProvider(); + const closedIssuesProvider = new ClosedIssuesProvider(); - vscode.window.registerTreeDataProvider('open-issues', openIssuesProvider); - vscode.window.registerTreeDataProvider('closed-issues', closedIssuesProvider); + vscode.window.registerTreeDataProvider('open-issues', openIssuesProvider); + vscode.window.registerTreeDataProvider('closed-issues', closedIssuesProvider); - // TODO: Implement in next version. - // vscode.commands.registerCommand('giteaIssues.createIssue', async () => { - // const panel = vscode.window.createWebviewPanel('createIssue', 'Create an new Issue', vscode.ViewColumn.Active, {}); - // panel.webview.html = ""; - // }); + // TODO: Implement in next version. + // vscode.commands.registerCommand('giteaIssues.createIssue', async () => { + // const panel = vscode.window.createWebviewPanel('createIssue', 'Create an new Issue', vscode.ViewColumn.Active, {}); + // panel.webview.html = ""; + // }); - vscode.commands.registerCommand('giteaIssues.openIssue', (issue: Issue) => { - for (let i = 0; i !== openIssues.length; i++) { - let openIssue = openIssues[i]; - if (openIssue.issueId === issue.issueId) { - return; - } + vscode.commands.registerCommand('giteaIssues.openIssue', (issue: Issue) => { + for (let i = 0; i !== openIssues.length; i++) { + let openIssue = openIssues[i]; + if (openIssue.issueId === issue.issueId) { + return; + } + } + const panel = vscode.window.createWebviewPanel('issue', issue.label, vscode.ViewColumn.Active, {}); + panel.webview.html = showIssueHTML(issue); + openIssues.push(issue); + panel.onDidDispose((event) => { + for (let i = 0; i !== openIssues.length; i++) { + let openIssue = openIssues[i]; + if (openIssue.issueId === issue.issueId) { + openIssues.splice(openIssues.indexOf(issue), 1); } - const panel = vscode.window.createWebviewPanel('issue', issue.label, - vscode.ViewColumn.Active, - {}); - panel.webview.html = showIssueHTML(issue); - openIssues.push(issue); - panel.onDidDispose(event => { - for (let i = 0; i !== openIssues.length; i++) { - let openIssue = openIssues[i]; - if (openIssue.issueId === issue.issueId) { - openIssues.splice(openIssues.indexOf(issue), 1); - } - } - }); - }); - - vscode.commands.registerCommand('giteaIssues.refreshIssues', () => { - openIssuesProvider.refresh(); - closedIssuesProvider.refresh(); + } }); + }); + vscode.commands.registerCommand('giteaIssues.refreshIssues', () => { + openIssuesProvider.refresh(); + closedIssuesProvider.refresh(); + }); } -export function deactivate() { } - -export async function initializeIssueTracker() { - if (vscode.workspace.rootPath === undefined) { - return vscode.window.showErrorMessage("No project opened!"); - } - let Token, Domain, Owner, Name; - await vscode.window.showInputBox({ - placeHolder: "Enter your gitea token here", - }).then(token => { - Token = token === undefined ? "" : token; - }); - await vscode.window.showInputBox({ - placeHolder: "Domain from your gitea server without 'https://'", - }).then(domain => { - Domain = domain === undefined ? "" : domain; - }); - await vscode.window.showInputBox({ - placeHolder: "Repository Owner", - }).then(owner => { - Owner = owner === undefined ? "" : owner; - }); - await vscode.window.showInputBox({ - placeHolder: "Repository Name", - }).then(name => { - Name = name === undefined ? "" : name; - }); - const repoInfo = { - token: Token, - domain: Domain, - repo_owner: Owner, - repo_name: Name, - }; - const rpim = new RepositoryInformationManager(); - rpim.saveRepoInformation(vscode.workspace.rootPath, repoInfo); -} \ No newline at end of file +export function deactivate() {} diff --git a/src/issue.ts b/src/issue.ts index e5f2932..ac71ed5 100644 --- a/src/issue.ts +++ b/src/issue.ts @@ -1,59 +1,54 @@ -import * as vscode from "vscode"; -import * as path from "path"; -import * as fs from "fs"; +import { Uri, TreeItem, TreeItemCollapsibleState, Command } from 'vscode'; -export class Issue extends vscode.TreeItem { - - constructor(public readonly label: string, - public issueId: number, - public body: string, - public issueState: string, - public assignee: string, - public creator: string, - public labels: any[], - public collapsibleState: vscode.TreeItemCollapsibleState, - public readonly command?: vscode.Command) { - super(label, collapsibleState); - try { - for (const issueLabel of labels) { - const folderPath = path.join(vscode.workspace.rootPath as string, '.gitea', 'label_pictures'); - if (!fs.existsSync(path.join(folderPath, issueLabel.name + ".svg"))) { - if (!fs.existsSync(folderPath)) { - fs.mkdirSync(folderPath); - } - fs.writeFileSync(path.join(folderPath, issueLabel.name + ".svg"), createIconWithColor(issueLabel.color)); - } - } - } catch (e) { - console.log(e); - } - } - - get tooltip() { - return this.label + " - " + this.assignee; - } - - labelDependentIcon(dark: boolean = false): string { - if (this.labels.length === 0) { - return path.join(__filename, '..', '..', 'media', 'issue.svg'); - } else { - return path.join(vscode.workspace.rootPath as string, '.gitea', 'label_pictures', this.labels[0].name + ".svg"); - } - } - - iconPath = { - light: this.labelDependentIcon(), - dark: this.labelDependentIcon(true) - }; - - contextValue = 'issue'; +interface Label { + color: string; + id: number; + name: string; + url: string; } -export function createIconWithColor(color: string) { - return ` - - - - -`.replace(new RegExp("{{color}}", 'g'), "#" + color); -} \ No newline at end of file +export class Issue extends TreeItem { + constructor( + public readonly label: string, + public issueId: number, + public body: string, + public issueState: string, + public assignee: string, + public creator: string, + public labels: Label[], + public collapsibleState: TreeItemCollapsibleState, + public readonly command?: Command + ) { + super(label, collapsibleState); + } + + get tooltip() { + return this.label + ' - ' + this.assignee; + } + + labelDependentIcon(dark: boolean = false): Uri { + if (this.labels.length === 0) { + return createIconWithColor('#868686'); + } else { + return createIconWithColor(this.labels[0].color); + } + } + + iconPath = { + light: this.labelDependentIcon(), + dark: this.labelDependentIcon(true), + }; + + contextValue = 'issue'; +} + +export function createIconWithColor(color: string): Uri { + const icon = ` + + + + + `.replace(new RegExp('{{color}}', 'g'), '#' + color); + + return Uri.parse('data:image/svg+xml;base64,' + Buffer.from(icon).toString('base64')); +} diff --git a/src/issueProvider.ts b/src/issueProvider.ts index 8ecdae2..bf1bbb2 100644 --- a/src/issueProvider.ts +++ b/src/issueProvider.ts @@ -1,159 +1,170 @@ -import axios from "axios"; -import * as vscode from "vscode"; +import axios from 'axios'; +import * as vscode from 'vscode'; -const marked = require("marked"); -import { Issue } from "./issue"; -import { RepositoryInformationManager } from "./configurationProvider"; +const marked = require('marked'); +import { Issue } from './issue'; +import { Config } from './Config'; export class OpenIssuesProvider implements vscode.TreeDataProvider { + private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); + readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; - private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); - readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; + issueList: Issue[] = []; - issueList: Issue[] = []; + async refresh() { + await this.getChildrenAsync(); + this._onDidChangeTreeData.fire(); + } - async refresh() { - await this.getChildrenAsync(); - this._onDidChangeTreeData.fire(); + constructor() { + // Auto update the issuelist after 10 minutes + setInterval(() => { + this.refresh(); + }, 10 * 60 * 1000); + } + + getTreeItem(element: Issue): vscode.TreeItem | Thenable { + return element; + } + + /** + * Returns a list of all open issues; + */ + async getChildrenAsync() { + this.issueList = []; + const config = new Config(); + const repoUri = config.repoApiUrl; + const token = config.token; + let stop = false; + for (let i = 0; i !== 10; i++) { + await axios + .get(repoUri + '?page=' + i, { headers: { Authorization: 'token ' + token } }) + .then((res) => { + console.log(res.data); + if (res.data.length === 0) { + stop = true; + return; + } + parseToIssues(res, this.issueList); + }) + .catch((err) => { + console.log(err); + stop = true; + vscode.window.showErrorMessage("Can't fetch issues; HTTP Error!"); + return; + }); + if (stop) { + return; + } } - - constructor() { - // Auto update the issuelist after 10 minutes - setInterval(() => { - this.refresh(); - }, 10 * 60 * 1000); - } - - getTreeItem(element: Issue): vscode.TreeItem | Thenable { - return element; - } - - /** - * Returns a list of all open issues; - */ - async getChildrenAsync() { - this.issueList = []; - const repoMng = new RepositoryInformationManager(); - const repoUri = repoMng.repoApiUrl(vscode.workspace.rootPath); - const token = repoMng.token(vscode.workspace.rootPath); - let stop = false; - for (let i = 0; i !== 10; i++) { - await axios.get(repoUri + "?page=" + i, { headers: { Authorization: "token " + token } }).then(res => { - console.log(res.data); - if (res.data.length === 0) { - stop = true; - return; - } - parseToIssues(res, this.issueList); - }).catch((err) => { - console.log(err); - stop = true; - vscode.window.showErrorMessage("Can't fetch issues; HTTP Error!"); - return; - }); - if (stop) { - return; - } - } - } - getChildren(element?: Issue): vscode.ProviderResult { - return getChildren(element, this.issueList); - } - - + } + getChildren(element?: Issue): vscode.ProviderResult { + return getChildren(element, this.issueList); + } } export class ClosedIssuesProvider implements vscode.TreeDataProvider { + private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); + readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; - private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); - readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; + issueList: Issue[] = []; - issueList: Issue[] = []; + async refresh() { + await this.getChildrenAsync(); + this._onDidChangeTreeData.fire(); + } - async refresh() { - await this.getChildrenAsync(); - this._onDidChangeTreeData.fire(); - } - - constructor() { - setInterval(() => { - this.refresh(); - }, 10 * 60 * 1000); - } - - getTreeItem(element: Issue): vscode.TreeItem | Thenable { - return element; - } - - async getChildrenAsync() { - this.issueList = []; - const repoMng = new RepositoryInformationManager(); - const repoUri = repoMng.repoApiUrl(vscode.workspace.rootPath); - const token = repoMng.token(vscode.workspace.rootPath); - let stop = false; - for (let i = 0; i !== 10; i++) { - await axios.get(repoUri + "?state=closed&page=" + i, { headers: { Authorization: "token " + token } }).then(res => { - console.log(res.data); - if (res.data.length === 0) { - stop = true; - return; - } - parseToIssues(res, this.issueList); - }).catch(() => { - stop = true; vscode.window.showErrorMessage("Can't fetch issues; HTTP Error!"); - return; - }); - if (stop) { - return; - } - } - } - getChildren(element?: Issue): vscode.ProviderResult { - return getChildren(element, this.issueList); + constructor() { + setInterval(() => { + this.refresh(); + }, 10 * 60 * 1000); + } + + getTreeItem(element: Issue): vscode.TreeItem | Thenable { + return element; + } + + async getChildrenAsync() { + this.issueList = []; + const config = new Config(); + const repoUri = config.repoApiUrl; + const token = config.token; + let stop = false; + for (let i = 0; i !== 10; i++) { + await axios + .get(repoUri + '?state=closed&page=' + i, { headers: { Authorization: 'token ' + token } }) + .then((res) => { + console.log(res.data); + if (res.data.length === 0) { + stop = true; + return; + } + parseToIssues(res, this.issueList); + }) + .catch(() => { + stop = true; + vscode.window.showErrorMessage("Can't fetch issues; HTTP Error!"); + return; + }); + if (stop) { + return; + } } + } + getChildren(element?: Issue): vscode.ProviderResult { + return getChildren(element, this.issueList); + } } export function getChildren(element: Issue | undefined, issueList: Issue[]) { - for (const issue of issueList) { - if (element === issue) { - let childItems: vscode.TreeItem[] = [ - new vscode.TreeItem("Assignee - " + element.assignee, vscode.TreeItemCollapsibleState.None), - new vscode.TreeItem("State - " + element.issueState, vscode.TreeItemCollapsibleState.None), - new vscode.TreeItem("ID - " + element.issueId, vscode.TreeItemCollapsibleState.None), - new vscode.TreeItem("From - " + element.creator, vscode.TreeItemCollapsibleState.None) - ]; - return Promise.resolve(childItems); - - } + for (const issue of issueList) { + if (element === issue) { + let childItems: vscode.TreeItem[] = [ + new vscode.TreeItem('Assignee - ' + element.assignee, vscode.TreeItemCollapsibleState.None), + new vscode.TreeItem('State - ' + element.issueState, vscode.TreeItemCollapsibleState.None), + new vscode.TreeItem('ID - ' + element.issueId, vscode.TreeItemCollapsibleState.None), + new vscode.TreeItem('From - ' + element.creator, vscode.TreeItemCollapsibleState.None), + ]; + return Promise.resolve(childItems); } - return issueList; + } + return issueList; } -export function parseToIssues(res: any, issueList: any[], collapsibleState: vscode.TreeItemCollapsibleState = vscode.TreeItemCollapsibleState.Collapsed) { - for (const issue of res.data) { - const id = issue["number"]; - let isAlreadyInList = false; - issueList.forEach((issueOfList) => { - if (id === issueOfList.issueId) { - isAlreadyInList = true; - } - }); - if (isAlreadyInList) { - continue; - } - const title = issue["title"]; - const body = marked(issue["body"]); - const state = issue["state"]; - const assignee = issue["assignee"] === null ? "None" : issue["assignee"]["username"]; - const labels = issue["labels"]; - const creator = issue["user"]["username"]; - const tmpIssue = new Issue("#" + id + " - " + title, id, body, state, assignee, creator, labels, collapsibleState); - const issueForList = new Issue(tmpIssue.label, tmpIssue.issueId, tmpIssue.body, tmpIssue.issueState, - tmpIssue.assignee, tmpIssue.creator, tmpIssue.labels, tmpIssue.collapsibleState, { - command: 'giteaIssues.openIssue', - title: '', - arguments: [tmpIssue], - }); - issueList.push(issueForList); +export function parseToIssues(res: any, issueList: Issue[], collapsibleState: vscode.TreeItemCollapsibleState = vscode.TreeItemCollapsibleState.Collapsed) { + for (const issue of res.data) { + const id = issue['number']; + let isAlreadyInList = false; + issueList.forEach((issueOfList) => { + if (id === issueOfList.issueId) { + isAlreadyInList = true; + } + }); + if (isAlreadyInList) { + continue; } -} \ No newline at end of file + const title = issue['title']; + const body = marked(issue['body']); + const state = issue['state']; + const assignee = issue['assignee'] === null ? 'None' : issue['assignee']['username']; + const labels = issue['labels']; + const creator = issue['user']['username']; + const tmpIssue = new Issue('#' + id + ' - ' + title, id, body, state, assignee, creator, labels, collapsibleState); + const issueForList = new Issue( + tmpIssue.label, + tmpIssue.issueId, + tmpIssue.body, + tmpIssue.issueState, + tmpIssue.assignee, + tmpIssue.creator, + tmpIssue.labels, + tmpIssue.collapsibleState, + { + command: 'giteaIssues.openIssue', + title: '', + arguments: [tmpIssue], + } + ); + issueList.push(issueForList); + } +} From 011232bc7593bd2f7415624dfcf5d16191992a00 Mon Sep 17 00:00:00 2001 From: ljoonal Date: Thu, 4 Jul 2019 15:45:53 +0300 Subject: [PATCH 2/2] A bit of cleanup --- .vscode/settings.json | 7 ++-- .vscodeignore | 3 +- src/template.html.ts | 74 ++++++++++++++++++++------------------ src/test/extension.test.ts | 7 +--- 4 files changed, 46 insertions(+), 45 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 30bf8c2..7ebedd4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,5 +7,8 @@ "out": true // set this to false to include "out" folder in search results }, // Turn off tsc task auto detection since we have the necessary tasks as npm scripts - "typescript.tsc.autoDetect": "off" -} \ No newline at end of file + "typescript.tsc.autoDetect": "off", + "editor.detectIndentation": false, + "prettier.tabWidth": 2, + "prettier.singleQuote": true +} diff --git a/.vscodeignore b/.vscodeignore index f6af244..ed3f9d3 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -7,5 +7,4 @@ vsc-extension-quickstart.md **/tsconfig.json **/tslint.json **/*.map -**/*.ts -.gitea/ \ No newline at end of file +**/*.ts \ No newline at end of file diff --git a/src/template.html.ts b/src/template.html.ts index ef3eb57..b4c743a 100644 --- a/src/template.html.ts +++ b/src/template.html.ts @@ -1,38 +1,42 @@ -import { Issue } from "./issue"; +import { Issue } from './issue'; export function showIssueHTML(issue: Issue) { - - return ` + return `

{{label}}

- - - - - - - - - - - - - -
- Title - - {{label}} -
- State - - {{state}} -
- Assignee - - {{assignee}} -
-

- {{description}} -

- -`.replace("{{label}}", issue.label).replace("{{state}}", issue.issueState).replace("{{assignee}}", issue.assignee).replace("{{description}}", issue.body).replace("{{label}}", issue.label); -} \ No newline at end of file + + + + + + + + + + + + + +
+ Title + + {{label}} +
+ State + + {{state}} +
+ Assignee + + {{assignee}} +
+

+ {{description}} +

+ + ` + .replace('{{label}}', issue.label) + .replace('{{state}}', issue.issueState) + .replace('{{assignee}}', issue.assignee) + .replace('{{description}}', issue.body) + .replace('{{label}}', issue.label); +} diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index a7a297f..1bd289d 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -4,7 +4,7 @@ // // The module 'assert' provides assertion methods from node -import * as assert from 'assert'; +//import * as assert from 'assert'; // You can import and use all API from the 'vscode' module // as well as import your extension to test it @@ -14,9 +14,4 @@ import * as assert from 'assert'; // Defines a Mocha test suite to group tests of similar kind together suite("Extension Tests", function () { - // Defines a Mocha unit test - test("Something 1", function() { - assert.equal(-1, [1, 2, 3].indexOf(5)); - assert.equal(-1, [1, 2, 3].indexOf(0)); - }); }); \ No newline at end of file