Merge pull request #61 from ecrider/master

New feature: Assign URLs to projects without custom filtering
This commit is contained in:
Alan Hamlett
2017-10-03 06:43:07 -07:00
committed by GitHub
15 changed files with 83 additions and 49 deletions

View File

@@ -142,11 +142,12 @@ var Options = React.createClass({
} }
return ( return (
<SitesList <SitesList
handleChange={that._updateWhitelistState} handleChange={that._updateWhitelistState}
label="Whitelist" label="Whitelist"
sites={that.state.whitelist} sites={that.state.whitelist}
helpText="Sites that you want to show in your reports." /> placeholder="http://google.com&#10;http://myproject.com@@MyProject"
helpText="Sites that you want to show in your reports. You can assign URL to project by adding @@YourProject at the end of line." />
); );
}; };

View File

@@ -67,6 +67,8 @@ var Wakatime = React.createClass({
totalTimeLoggedToday: grand_total.text totalTimeLoggedToday: grand_total.text
}); });
}); });
wakatime.recordHeartbeat();
} }
else { else {
changeExtensionState('notSignedIn'); changeExtensionState('notSignedIn');

View File

@@ -3,7 +3,6 @@
var $ = require('jquery'); var $ = require('jquery');
var moment = require('moment'); var moment = require('moment');
var config = require('./../config'); var config = require('./../config');
// Helpers // Helpers
@@ -29,7 +28,6 @@ class WakaTimeCore {
getTotalTimeLoggedToday() { getTotalTimeLoggedToday() {
var deferredObject = $.Deferred(); var deferredObject = $.Deferred();
var today = moment().format('YYYY-MM-DD'); var today = moment().format('YYYY-MM-DD');
$.ajax({ $.ajax({
@@ -63,14 +61,10 @@ class WakaTimeCore {
url: config.currentUserApiUrl, url: config.currentUserApiUrl,
dataType: 'json', dataType: 'json',
success: (data) => { success: (data) => {
deferredObject.resolve(data.data); deferredObject.resolve(data.data);
}, },
error: (xhr, status, err) => { error: (xhr, status, err) => {
console.error(config.currentUserApiUrl, status, err.toString()); console.error(config.currentUserApiUrl, status, err.toString());
deferredObject.resolve(false); deferredObject.resolve(false);
} }
}); });
@@ -83,7 +77,6 @@ class WakaTimeCore {
* and sends it to WakaTime for logging. * and sends it to WakaTime for logging.
*/ */
recordHeartbeat() { recordHeartbeat() {
chrome.storage.sync.get({ chrome.storage.sync.get({
loggingEnabled: config.loggingEnabled, loggingEnabled: config.loggingEnabled,
loggingStyle: config.loggingStyle, loggingStyle: config.loggingStyle,
@@ -91,24 +84,27 @@ class WakaTimeCore {
whitelist: '' whitelist: ''
}, (items) => { }, (items) => {
if (items.loggingEnabled === true) { if (items.loggingEnabled === true) {
changeExtensionState('allGood'); changeExtensionState('allGood');
chrome.idle.queryState(config.detectionIntervalInSeconds, (newState) => { chrome.idle.queryState(config.detectionIntervalInSeconds, (newState) => {
if (newState === 'active') { if (newState === 'active') {
// Get current tab URL. // Get current tab URL.
chrome.tabs.query({active: true}, (tabs) => { chrome.tabs.query({active: true}, (tabs) => {
var currentActiveTab = tabs[0]; var currentActiveTab = tabs[0];
var debug = false; var debug = false;
// If the current active tab has devtools open // If the current active tab has devtools open
if (in_array(currentActiveTab.id, this.tabsWithDevtoolsOpen)) debug = true; if (in_array(currentActiveTab.id, this.tabsWithDevtoolsOpen)) {
debug = true;
}
if (items.loggingStyle == 'blacklist') { if (items.loggingStyle == 'blacklist') {
if (! contains(currentActiveTab.url, items.blacklist)) { if (! contains(currentActiveTab.url, items.blacklist)) {
this.sendHeartbeat(currentActiveTab.url, debug); this.sendHeartbeat({
url: currentActiveTab.url,
project: false
}, debug);
} }
else { else {
changeExtensionState('blacklisted'); changeExtensionState('blacklisted');
@@ -117,8 +113,9 @@ class WakaTimeCore {
} }
if (items.loggingStyle == 'whitelist') { if (items.loggingStyle == 'whitelist') {
if (contains(currentActiveTab.url, items.whitelist)) { var heartbeat = this.getHeartbeat(currentActiveTab.url, items.whitelist);
this.sendHeartbeat(currentActiveTab.url, debug); if (heartbeat.url) {
this.sendHeartbeat(heartbeat, debug);
} }
else { else {
changeExtensionState('whitelisted'); changeExtensionState('whitelisted');
@@ -136,6 +133,50 @@ class WakaTimeCore {
}); });
} }
/**
* Creates an array from list using \n as delimiter
* and checks if any element in list is contained in the url.
* Also checks if element is assigned to a project using @@ as delimiter
*
* @param url
* @param list
* @returns {object}
*/
getHeartbeat(url, list) {
var lines = list.split('\n');
for (var i = 0; i < lines.length; i ++) {
// Trim all lines from the list one by one
var cleanLine = lines[i].trim();
// If by any chance one line in the list is empty, ignore it
if (cleanLine === '') {
continue;
}
// If url contains the current line return object
if (url.indexOf(cleanLine.split('@@')[0]) > -1) {
if (cleanLine.split('@@')[1]) {
return {
url: cleanLine.split('@@')[0],
project: cleanLine.split('@@')[1]
};
}
else {
return {
url: cleanLine.split('@@')[0],
project: false
};
}
}
}
return {
url: false,
project: false
};
}
/** /**
* Creates payload for the heartbeat and returns it as JSON. * Creates payload for the heartbeat and returns it as JSON.
* *
@@ -145,12 +186,12 @@ class WakaTimeCore {
* @returns {*} * @returns {*}
* @private * @private
*/ */
_preparePayload(entity, type, debug = false) { _preparePayload(heartbeat, type, debug = false) {
return JSON.stringify({ return JSON.stringify({
entity: entity, entity: heartbeat.url,
type: type, type: type,
time: moment().format('X'), time: moment().format('X'),
project: '<<LAST_PROJECT>>', project: heartbeat.project || '<<LAST_PROJECT>>',
is_debugging: debug, is_debugging: debug,
plugin: 'chrome-wakatime/' + config.version plugin: 'chrome-wakatime/' + config.version
}); });
@@ -182,34 +223,24 @@ class WakaTimeCore {
* @param entity * @param entity
* @param debug * @param debug
*/ */
sendHeartbeat(entity, debug) { sendHeartbeat(heartbeat, debug) {
var payload = null; var payload = null;
this._getLoggingType().done((loggingType) => { this._getLoggingType().done((loggingType) => {
// Get only the domain from the entity. // Get only the domain from the entity.
// And send that in heartbeat // And send that in heartbeat
if (loggingType == 'domain') { if (loggingType == 'domain') {
heartbeat.url = getDomainFromUrl(heartbeat.url);
var domain = getDomainFromUrl(entity); payload = this._preparePayload(heartbeat, 'domain', debug);
payload = this._preparePayload(domain, 'domain', debug);
console.log(payload); console.log(payload);
this.sendAjaxRequestToApi(payload); this.sendAjaxRequestToApi(payload);
} }
// Send entity in heartbeat // Send entity in heartbeat
else if (loggingType == 'url') { else if (loggingType == 'url') {
payload = this._preparePayload(entity, 'url', debug); payload = this._preparePayload(heartbeat, 'url', debug);
console.log(payload); console.log(payload);
this.sendAjaxRequestToApi(payload); this.sendAjaxRequestToApi(payload);
} }
}); });
} }

View File

@@ -1,6 +1,6 @@
/*! /*!
* Bootstrap v3.3.6 (http://getbootstrap.com) * Bootstrap v3.3.7 (http://getbootstrap.com)
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/ */

View File

@@ -59,7 +59,7 @@
.border-right-radius(0); .border-right-radius(0);
} }
} }
// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it // Need .dropdown-toggle since :last-child doesn't apply, given that a .dropdown-menu is used immediately after it
.btn-group > .btn:last-child:not(:first-child), .btn-group > .btn:last-child:not(:first-child),
.btn-group > .dropdown-toggle:not(:first-child) { .btn-group > .dropdown-toggle:not(:first-child) {
.border-left-radius(0); .border-left-radius(0);

View File

@@ -181,7 +181,7 @@ input[type="search"] {
// set a pixel line-height that matches the given height of the input, but only // set a pixel line-height that matches the given height of the input, but only
// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848 // for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848
// //
// Note that as of 8.3, iOS doesn't support `datetime` or `week`. // Note that as of 9.3, iOS doesn't support `week`.
@media screen and (-webkit-min-device-pixel-ratio: 0) { @media screen and (-webkit-min-device-pixel-ratio: 0) {
input[type="date"], input[type="date"],

View File

@@ -1,9 +1,9 @@
// WebKit-style focus // WebKit-style focus
.tab-focus() { .tab-focus() {
// Default // WebKit-specific. Other browsers will keep their default outline style.
outline: thin dotted; // (Initially tried to also force default via `outline: initial`,
// WebKit // but that seems to erroneously remove the outline in Firefox altogether.)
outline: 5px auto -webkit-focus-ring-color; outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px; outline-offset: -2px;
} }

View File

@@ -214,7 +214,7 @@
} }
// Collapsable panels (aka, accordion) // Collapsible panels (aka, accordion)
// //
// Wrap a series of panels in `.panel-group` to turn them into an accordion with // Wrap a series of panels in `.panel-group` to turn them into an accordion with
// the help of our collapse JavaScript plugin. // the help of our collapse JavaScript plugin.

View File

@@ -120,7 +120,7 @@ hr {
// Only display content to screen readers // Only display content to screen readers
// //
// See: http://a11yproject.com/posts/how-to-hide-content/ // See: http://a11yproject.com/posts/how-to-hide-content
.sr-only { .sr-only {
position: absolute; position: absolute;

View File

@@ -1,6 +1,6 @@
/*! /*!
* Bootstrap v3.3.6 (http://getbootstrap.com) * Bootstrap v3.3.7 (http://getbootstrap.com)
* Copyright 2011-2015 Twitter, Inc. * Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/ */

View File

@@ -111,7 +111,7 @@
//** Global background color for active items (e.g., navs or dropdowns). //** Global background color for active items (e.g., navs or dropdowns).
@component-active-bg: @brand-primary; @component-active-bg: @brand-primary;
//** Width of the `border` for generating carets that indicator dropdowns. //** Width of the `border` for generating carets that indicate dropdowns.
@caret-width-base: 4px; @caret-width-base: 4px;
//** Carets increase slightly in size for larger components. //** Carets increase slightly in size for larger components.
@caret-width-large: 5px; @caret-width-large: 5px;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 58 KiB