Added API integration.

This commit is contained in:
Juha Ristolainen 2017-03-17 14:30:17 +00:00
parent cb048907f3
commit 768f37d9e8
6 changed files with 136 additions and 19 deletions

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,8 +1,8 @@
{ {
"name": "code-stats-vscode", "name": "code-stats-vscode",
"displayName": "code-stats-vscode", "displayName": "Code::Stats",
"description": "Code::Stats package for Visual Studio Code", "description": "Code::Stats package for Visual Studio Code",
"version": "0.0.1", "version": "0.1.0",
"publisher": "juha-ristolainen", "publisher": "juha-ristolainen",
"engines": { "engines": {
"vscode": "^1.10.0" "vscode": "^1.10.0"
@ -10,11 +10,25 @@
"categories": [ "categories": [
"Other" "Other"
], ],
"maintainers": [
"Juha Ristolainen"
],
"activationEvents": [ "activationEvents": [
"*" "*"
], ],
"main": "./out/src/code-stats", "main": "./out/src/code-stats",
"contributes": { "contributes": {
"configuration": {
"type": "object",
"title": "code-stats-vscode",
"properties": {
"codestats.apikey": {
"type": "string",
"default": "",
"description": "Code::Stats API key for this machine."
}
}
},
"commands": [] "commands": []
}, },
"scripts": { "scripts": {
@ -29,5 +43,8 @@
"mocha": "^2.3.3", "mocha": "^2.3.3",
"@types/node": "^6.0.40", "@types/node": "^6.0.40",
"@types/mocha": "^2.2.32" "@types/mocha": "^2.2.32"
},
"dependencies": {
"axios": "0.15.3"
} }
} }

68
src/code-stats-api.ts Normal file
View File

@ -0,0 +1,68 @@
import { Pulse } from "./pulse";
import { getISOTimestamp } from "./utils";
import * as axios from "axios";
export class CodeStatsAPI {
private API_KEY = null;
private UPDATE_URL = "https://codestats.net/api/my/pulses";
private axios;
constructor(apiKey: string) {
this.API_KEY = apiKey;
if (this.API_KEY === null || this.API_KEY === undefined) {
return;
}
this.axios = axios.default.create({
baseURL: this.UPDATE_URL,
timeout: 1000,
headers: {
"X-API-Token": this.API_KEY,
"Content-Type": "application/json"
}
});
}
public sendUpdate(pulse: Pulse): void {
// tslint:disable-next-line:typedef
const data = new ApiJSON(new Date());
for (let lang of pulse.xps.keys()) {
let xp: number = pulse.getXP(lang);
data.xps.push(new ApiXP(lang, xp));
}
let json: string = JSON.stringify(data);
console.log(`JSON: ${json}`);
this.axios.post(this.UPDATE_URL, json)
.then( (response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
}
}
class ApiJSON {
constructor(date: Date) {
this.coded_at = getISOTimestamp(new Date());
this.xps = new Array<ApiXP>();
}
coded_at: string;
xps: Array<ApiXP>;
}
class ApiXP {
constructor(language: string, xp: number) {
this.language = language;
this.xp = xp;
}
language: string;
xp: number;
}

View File

@ -3,15 +3,10 @@ import { ExtensionContext } from "vscode";
import { XpCounter } from "./xp-counter"; import { XpCounter } from "./xp-counter";
export function activate(context: ExtensionContext): void { export function activate(context: ExtensionContext): void {
console.log("Activating code-stats-vscode");
let controller: XpCounter = new XpCounter(); let controller: XpCounter = new XpCounter();
// add to a list of disposables which are disposed when this extension is deactivated.
context.subscriptions.push(controller); context.subscriptions.push(controller);
} }
// this method is called when your extension is deactivated // this method is called when your extension is deactivated
export function deactivate(): void { export function deactivate(): void {
console.log("Deactivating code-stats-vscode");
} }

View File

@ -2,7 +2,6 @@ export class Pulse {
xps: Map < string, number > ; xps: Map < string, number > ;
constructor() { constructor() {
console.log("Creating Pulse");
this.xps = new Map < string, number > (); this.xps = new Map < string, number > ();
} }
@ -22,7 +21,13 @@ export class Pulse {
xp += amount; xp += amount;
this.xps.set(language, xp); this.xps.set(language, xp);
}
// console.log(`Added ${amount} of XP to ${language}, total is now ${xp}`); public get getXPs(): Map < string, number > {
return this.xps;
}
public reset(): void {
this.xps = new Map < string, number > ();
} }
} }

View File

@ -1,17 +1,32 @@
import { Disposable, workspace, window, StatusBarItem, TextDocument, StatusBarAlignment, TextDocumentChangeEvent, Range } from "vscode"; // tslint:disable-next-line:max-line-length
import { Disposable, workspace, window, StatusBarItem, TextDocument, StatusBarAlignment, TextDocumentChangeEvent, Range, WorkspaceConfiguration } from "vscode";
import { Pulse } from "./pulse"; import { Pulse } from "./pulse";
import { CodeStatsAPI } from "./code-stats-api";
export class XpCounter { export class XpCounter {
private combinedDisposable: Disposable; private combinedDisposable: Disposable;
private statusBarItem: StatusBarItem; private statusBarItem: StatusBarItem;
private pulse: Pulse; private pulse: Pulse;
private languages: Array<string> = ["typescript", "javascript"]; private api: CodeStatsAPI;
private changeCount: number = 0; private updateTimeout: any;
// private languages: Array<string> = ["typescript", "javascript"];
// wait 10s after each change in the document before sending an update
private UPDATE_DELAY = 10000;
constructor() { constructor() {
console.log(`Supported languages for Code::Stats are ${this.languages}`);
this.pulse = new Pulse(); this.pulse = new Pulse();
let config: WorkspaceConfiguration = workspace.getConfiguration("codestats");
if (!config) {
return;
}
// tslint:disable-next-line:typedef
let apiKey = config.get("apikey");
this.api = new CodeStatsAPI(`${apiKey}`);
if (!this.statusBarItem) { if (!this.statusBarItem) {
this.statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left); this.statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left);
} }
@ -43,7 +58,6 @@ export class XpCounter {
if (range.start.character === range.end.character) { if (range.start.character === range.end.character) {
return 1; return 1;
} else { } else {
console.log(`L${range.start.line}C${range.start.character} to L${range.end.line}C${range.end.character}`);
return range.end.character - range.start.character; return range.end.character - range.start.character;
} }
} }
@ -52,20 +66,38 @@ export class XpCounter {
} }
public updateXpCount(document: TextDocument, changeCount: number): void { public updateXpCount(document: TextDocument, changeCount: number): void {
// only update xp if one of supported languages let show: boolean;
if (this.isSupportedLanguage(document.languageId)) { if (this.isSupportedLanguage(document.languageId)) {
this.pulse.addXP(document.languageId, changeCount); this.pulse.addXP(document.languageId, changeCount);
// this.statusBarItem.text = this.changeCount !== 1 ? show = true;
// ` C::S ${this.changeCount} Words` : "$(pencil) C::S 1 Word";
this.statusBarItem.text = `C::S $(pencil) ${this.pulse.getXP(document.languageId)}`;
this.statusBarItem.show();
} else { } else {
show = false;
}
this.updateStatusBar(show, `${this.pulse.getXP(document.languageId)}`);
// each change resets the timeout so we only send updates when there is a 10s delay in updates to the document
if (this.updateTimeout !== null) {
clearTimeout(this.updateTimeout);
}
this.updateTimeout = setTimeout(() => {
this.api.sendUpdate(this.pulse);
}, this.UPDATE_DELAY);
}
private updateStatusBar(show: boolean, changeCount: string): void {
if (!show) {
this.statusBarItem.hide(); this.statusBarItem.hide();
} else {
this.statusBarItem.text = `$(pencil) C::S ${changeCount}`;
this.statusBarItem.show();
} }
} }
private isSupportedLanguage(language: string): boolean { private isSupportedLanguage(language: string): boolean {
// todo: check supported languages // todo: check supported languages
// only update xp if one of supported languages
return true; return true;
} }