Skip to content
Snippets Groups Projects
Commit ebd09e66 authored by jurgenhaas's avatar jurgenhaas
Browse files

initial commit

parents
No related branches found
No related tags found
No related merge requests found
/*------------------------------------------------------------------------
* CSS Library for Toggl-Button for Greasemonkey
*
* (c) Jürgen Haas
* Version: 1.3
*
* @see https://github.com/jurgenhaas/toggl-button-greasemonkey
*------------------------------------------------------------------------
*/
#toggl-button-gi-wrapper {
position: fixed;
bottom: 10px;
right: 10px;
z-index: 9;
display: none;
padding: 0 0 0 30px;
border: 1px solid #999999;
-moz-box-shadow: 0 0 5px 5px #888;
-webkit-box-shadow: 0 0 5px 5px #888;
box-shadow: 0 0 5px 5px #888;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAFa9AABWvQE1bkh1AAAAB3RJTUUH3QQeBxszNJufNAAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAANsSURBVDjLrZRPaFxVFMZ/57735s1LMzMxmca0nQRCqkmTmgZSUUs1BYM70YK4CCgKunTRvQsVXRZD92rdCEWKiyhoFWOKFRFsWg1pMW1jpyltJpNkJvMv781797pI86zSShfe1eWecz++7zt/4H88cr/ANNhd3f2dKmnlxEpkmhJpKzIra/XS0jdLS6V3QT8ImMwPDAwl7eRRUda4KOkzSItgtDGmHEVmrqmjrwrV9amxfP7WfcGmwe4ZHHnRcqy3RNSTiDgiEucYYwyA1rrqR9GXa74/eWhh/pd7gcnC4MhLtmO/o5TadzeIlduDrlYxpXKcbLSO6mF05maj/vb41cvnAazt4PzA8H43Yb+nlDV6N5CkU6ReexVJpQivXgO9ZZWIKEek1xZx9vrOuTP+RsPalpftyr1p2WpCRNkAKEXi4CjuwVESg/sQ28bavQtdq2HK5RhQRHKtLnMn14qXFUBXf3+nWDIO4mwzcg89ResrE6i2DIQhJghwHn2E1BuvY+X2xHITIh2enRg/Bp4CUFYyJ0LftjxJp/CeGye48Bu1019gggBdWKHyyaeIskgeGQOl7vggyrPUY93ZnjYFIEoygrTEhu/ciZXtYPPcT9DYBGPAGPSt2/gXLuLs7QPXjdkpkXbPjVptAB1F2ti2/tv1O7cowoQhjbM/Et1ejt9QChHBxC2DrosYBdAMddEYKW/3UVRcRZfKuE88DsDmd9/T/H0O1f4QieH9hIt/Ynw/ZrapdaEYBBUboNIo3/Bcd04puxfAlEo0pn9gxwvPI46DP3sRafHwnj6MeC1szpzdYghoo6NS0/91tlAoWQC5jQ1/MNuZsix1RIlyAcLreUy9TmLkAN4zh3GHhohWV6l9fppw4Uo8EZUwzM/Vyic+3Nj4I7Zppqdn18PpjuOebb8sSsXNLK2tqEwaE0Xo9XXwg1heEEX1xXrtxPsLlz6YgWr86WS5XJ3ItN+wldXtiPSKyFbtgwBTqWCqtViaMcY0tW4sNRqnpgrFyVN+bfkf4wTw0drKzaOplku2WI4IOQXJfy8DY0xYicLrS43Gx1OF4uRkuXDtP/fZ8XS6/UB291jGtZ91lT2sRNoN6E0dLa83g/OLfv3bz/L5n2eg+kDLEeAYeN3ZbFsimdzh+1CsB5XZWqH0Nfj3yv8LMvl8kMnBqycAAAAASUVORK5CYII=) no-repeat left top;
background-color: #ffffff;
font-size: 12px;
font-family: sans-serif;
}
#toggl-button-gi-wrapper.active {
display: block;
}
#toggl-button-gi-wrapper:hover {
cursor: pointer;
}
#toggl-button-gi-wrapper.collapsed {
width: 20px;
height: 20px;
overflow: hidden;
padding: 0;
}
#toggl-button-gi-wrapper div.content {
margin: 0;
padding: 2px;
min-height: 0;
color: #000;
}
#toggl-button-gi-wrapper.collapsed div.content {
display: none;
}
#toggl-button-gi-wrapper div div {
display: inline-block;
margin: 0 2px;
}
#toggl-button-gi-wrapper div.project {
font-weight: bold;
background: none;
}
.toggl-button-active #toggl-button-gi-wrapper {
display: none;
}
#toggl-button-wrapper {
position: fixed;
bottom: 10px;
left: 10px;
z-index: 999;
padding: 0;
border: 1px solid #999999;
-moz-box-shadow: 0 0 5px 5px #888;
-webkit-box-shadow: 0 0 5px 5px #888;
box-shadow: 0 0 5px 5px #888;
font-size: 12px;
font-family: sans-serif;
}
#toggl-button-wrapper .content {
background-color: #dddddd;
padding: 0;
margin: 0;
}
#toggl-button-wrapper .content .toggl-button-project-select {
border: none;
}
.toggl-button {
display: inline-block !important;
line-height: 20px;
padding-left: 23px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAFa9AABWvQE1bkh1AAAAB3RJTUUH3QQeBxszNJufNAAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAANsSURBVDjLrZRPaFxVFMZ/57735s1LMzMxmca0nQRCqkmTmgZSUUs1BYM70YK4CCgKunTRvQsVXRZD92rdCEWKiyhoFWOKFRFsWg1pMW1jpyltJpNkJvMv781797pI86zSShfe1eWecz++7zt/4H88cr/ANNhd3f2dKmnlxEpkmhJpKzIra/XS0jdLS6V3QT8ImMwPDAwl7eRRUda4KOkzSItgtDGmHEVmrqmjrwrV9amxfP7WfcGmwe4ZHHnRcqy3RNSTiDgiEucYYwyA1rrqR9GXa74/eWhh/pd7gcnC4MhLtmO/o5TadzeIlduDrlYxpXKcbLSO6mF05maj/vb41cvnAazt4PzA8H43Yb+nlDV6N5CkU6ReexVJpQivXgO9ZZWIKEek1xZx9vrOuTP+RsPalpftyr1p2WpCRNkAKEXi4CjuwVESg/sQ28bavQtdq2HK5RhQRHKtLnMn14qXFUBXf3+nWDIO4mwzcg89ResrE6i2DIQhJghwHn2E1BuvY+X2xHITIh2enRg/Bp4CUFYyJ0LftjxJp/CeGye48Bu1019gggBdWKHyyaeIskgeGQOl7vggyrPUY93ZnjYFIEoygrTEhu/ciZXtYPPcT9DYBGPAGPSt2/gXLuLs7QPXjdkpkXbPjVptAB1F2ti2/tv1O7cowoQhjbM/Et1ejt9QChHBxC2DrosYBdAMddEYKW/3UVRcRZfKuE88DsDmd9/T/H0O1f4QieH9hIt/Ynw/ZrapdaEYBBUboNIo3/Bcd04puxfAlEo0pn9gxwvPI46DP3sRafHwnj6MeC1szpzdYghoo6NS0/91tlAoWQC5jQ1/MNuZsix1RIlyAcLreUy9TmLkAN4zh3GHhohWV6l9fppw4Uo8EZUwzM/Vyic+3Nj4I7Zppqdn18PpjuOebb8sSsXNLK2tqEwaE0Xo9XXwg1heEEX1xXrtxPsLlz6YgWr86WS5XJ3ItN+wldXtiPSKyFbtgwBTqWCqtViaMcY0tW4sNRqnpgrFyVN+bfkf4wTw0drKzaOplku2WI4IOQXJfy8DY0xYicLrS43Gx1OF4uRkuXDtP/fZ8XS6/UB291jGtZ91lT2sRNoN6E0dLa83g/OLfv3bz/L5n2eg+kDLEeAYeN3ZbFsimdzh+1CsB5XZWqH0Nfj3yv8LMvl8kMnBqycAAAAASUVORK5CYII=) no-repeat left top;
}
.toggl-button.hidden {
display: none !important;
}
.toggl-button.min {
height: 19px;
padding-left: 19px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAABIklEQVR4AYWSu0qDURCEN80fkUCwSCPk8iJ5DF/BF1Aw1Ye2NhpLQSwFn8EiMd4qb6WNEDCkEdIETVLogDm7RyzMMvwzO8ue4eRY/GiyQ583ZsKleBNLlcgqh8z5yku6q342VuM+7LzUr6WxgrvMmHAuuJZX/hk7kIh6xoSsI9+MBotIo4QnmJAlld8ydl1OaVPhFBMq4lN39owrF9us87o89EV8y50bY+SrqxxHNvGqx3k3Zks6lP2UjT1iDNO+2DahRC+7kJ70JLYNPEGbjbgG8bbza6Pj4paCTcZiY30L6eR0jDofLi9oUGJNaIin7id1w9gXjavscyYsoiffDKMc/+nfkrfy/wt5kPfrvXX9oAhwFO8tqkWHASPmwkC8Fd430YaitSJltegAAAAASUVORK5CYII=) no-repeat left top;
}
.toggl-button.min.active {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAFa9AABWvQE1bkh1AAAAB3RJTUUH3QQeBxszNJufNAAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAANsSURBVDjLrZRPaFxVFMZ/57735s1LMzMxmca0nQRCqkmTmgZSUUs1BYM70YK4CCgKunTRvQsVXRZD92rdCEWKiyhoFWOKFRFsWg1pMW1jpyltJpNkJvMv781797pI86zSShfe1eWecz++7zt/4H88cr/ANNhd3f2dKmnlxEpkmhJpKzIra/XS0jdLS6V3QT8ImMwPDAwl7eRRUda4KOkzSItgtDGmHEVmrqmjrwrV9amxfP7WfcGmwe4ZHHnRcqy3RNSTiDgiEucYYwyA1rrqR9GXa74/eWhh/pd7gcnC4MhLtmO/o5TadzeIlduDrlYxpXKcbLSO6mF05maj/vb41cvnAazt4PzA8H43Yb+nlDV6N5CkU6ReexVJpQivXgO9ZZWIKEek1xZx9vrOuTP+RsPalpftyr1p2WpCRNkAKEXi4CjuwVESg/sQ28bavQtdq2HK5RhQRHKtLnMn14qXFUBXf3+nWDIO4mwzcg89ResrE6i2DIQhJghwHn2E1BuvY+X2xHITIh2enRg/Bp4CUFYyJ0LftjxJp/CeGye48Bu1019gggBdWKHyyaeIskgeGQOl7vggyrPUY93ZnjYFIEoygrTEhu/ciZXtYPPcT9DYBGPAGPSt2/gXLuLs7QPXjdkpkXbPjVptAB1F2ti2/tv1O7cowoQhjbM/Et1ejt9QChHBxC2DrosYBdAMddEYKW/3UVRcRZfKuE88DsDmd9/T/H0O1f4QieH9hIt/Ynw/ZrapdaEYBBUboNIo3/Bcd04puxfAlEo0pn9gxwvPI46DP3sRafHwnj6MeC1szpzdYghoo6NS0/91tlAoWQC5jQ1/MNuZsix1RIlyAcLreUy9TmLkAN4zh3GHhohWV6l9fppw4Uo8EZUwzM/Vyic+3Nj4I7Zppqdn18PpjuOebb8sSsXNLK2tqEwaE0Xo9XXwg1heEEX1xXrtxPsLlz6YgWr86WS5XJ3ItN+wldXtiPSKyFbtgwBTqWCqtViaMcY0tW4sNRqnpgrFyVN+bfkf4wTw0drKzaOplku2WI4IOQXJfy8DY0xYicLrS43Gx1OF4uRkuXDtP/fZ8XS6/UB291jGtZ91lT2sRNoN6E0dLa83g/OLfv3bz/L5n2eg+kDLEeAYeN3ZbFsimdzh+1CsB5XZWqH0Nfj3yv8LMvl8kMnBqycAAAAASUVORK5CYII=) no-repeat left top;
}
.toggl-button-project-select {
display: inline-block;
width: 150px;
height: 14px;
line-height: 0;
overflow: hidden;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAABIklEQVR4AYWSu0qDURCEN80fkUCwSCPk8iJ5DF/BF1Aw1Ye2NhpLQSwFn8EiMd4qb6WNEDCkEdIETVLogDm7RyzMMvwzO8ue4eRY/GiyQ583ZsKleBNLlcgqh8z5yku6q342VuM+7LzUr6WxgrvMmHAuuJZX/hk7kIh6xoSsI9+MBotIo4QnmJAlld8ydl1OaVPhFBMq4lN39owrF9us87o89EV8y50bY+SrqxxHNvGqx3k3Zks6lP2UjT1iDNO+2DahRC+7kJ70JLYNPEGbjbgG8bbza6Pj4paCTcZiY30L6eR0jDofLi9oUGJNaIin7id1w9gXjavscyYsoiffDKMc/+nfkrfy/wt5kPfrvXX9oAhwFO8tqkWHASPmwkC8Fd430YaitSJltegAAAAASUVORK5CYII=) no-repeat right #ddd;
border: 1px solid #ccc;
margin-left: 5px;
}
.toggl-button-project-select select {
background: transparent;
width: 268px;
padding: 0 2px;
font-size: 10px;
line-height: 1em;
border: 0;
border-radius: 0;
height: 12px;
-webkit-appearance: none;
}
#toggl-button-auth-failed {
display: block;
position: fixed;
z-index: 999;
top: 0;
left: 0;
right: 0;
height: 25px;
padding: 5px;
background-color: #ff0000;
color: #ffffff;
text-align: center;
font-weight: bold;
}
#toggl-button-auth-failed .content {
display: inline-block;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAABIklEQVR4AYWSu0qDURCEN80fkUCwSCPk8iJ5DF/BF1Aw1Ye2NhpLQSwFn8EiMd4qb6WNEDCkEdIETVLogDm7RyzMMvwzO8ue4eRY/GiyQ583ZsKleBNLlcgqh8z5yku6q342VuM+7LzUr6WxgrvMmHAuuJZX/hk7kIh6xoSsI9+MBotIo4QnmJAlld8ydl1OaVPhFBMq4lN39owrF9us87o89EV8y50bY+SrqxxHNvGqx3k3Zks6lP2UjT1iDNO+2DahRC+7kJ70JLYNPEGbjbgG8bbza6Pj4paCTcZiY30L6eR0jDofLi9oUGJNaIin7id1w9gXjavscyYsoiffDKMc/+nfkrfy/wt5kPfrvXX9oAhwFO8tqkWHASPmwkC8Fd430YaitSJltegAAAAASUVORK5CYII=) no-repeat left top;
padding-left: 35px;
}
#toggl-button-auth-failed .content a {
padding-left: 10px;
color: #ffffff;
text-decoration: underline;
}
/* Special positioning on TeamWork */
body#tasks #toggl-button-wrapper {
bottom: 40px;
}
/*------------------------------------------------------------------------
* JavaScript Library for Toggl-Button for Greasemonkey
*
* (c) Jürgen Haas
* Version: 1.3
*
* @see https://github.com/jurgenhaas/toggl-button-greasemonkey
*------------------------------------------------------------------------
*/
function TogglButtonGM(selector, renderer) {
var
$activeApiUrl = null,
$apiUrl = "https://www.toggl.com/api/v7",
$newApiUrl = "https://www.toggl.com/api/v8",
$legacyApiUrl = "https://new.toggl.com/api/v8",
$triedAlternative = false,
$api_token = null,
$default_wid = null,
$clientMap = {},
$projectMap = {},
$instances = {};
init(selector, renderer);
function init(selector, renderer, apiUrl) {
var timeNow = new Date().getTime(),
timeAuth = GM_getValue('_authenticated', 0);
apiUrl = apiUrl || $newApiUrl;
$api_token = GM_getValue('_api_token', false);
if ($api_token && (timeNow - timeAuth) < (6*60*60*1000)) {
$activeApiUrl = GM_getValue('_api_url', $newApiUrl);
$default_wid = GM_getValue('_default_wid', 0);
$clientMap = JSON.parse(GM_getValue('_clientMap', {}));
$projectMap = JSON.parse(GM_getValue('_projectMap', {}));
if ($activeApiUrl == $legacyApiUrl) {
// See issue #22.
$activeApiUrl = $newApiUrl;
GM_setValue('_api_url', $activeApiUrl);
}
render(selector, renderer);
return;
}
var headers = {};
if ($api_token) {
headers = {
"Authorization": "Basic " + btoa($api_token + ':api_token')
};
}
$activeApiUrl = apiUrl;
GM_xmlhttpRequest({
method: "GET",
url: apiUrl + "/me?with_related_data=true",
headers: headers,
onload: function(result) {
if (result.status === 200) {
var resp = JSON.parse(result.responseText);
$clientMap[0] = 'No Client';
if (resp.data.clients) {
resp.data.clients.forEach(function (client) {
$clientMap[client.id] = client.name;
});
}
if (resp.data.projects) {
resp.data.projects.forEach(function (project) {
if ($clientMap[project.cid] == undefined) {
project.cid = 0;
}
if (project.active) {
$projectMap[project.id] = {
id: project.id,
cid: project.cid,
name: project.name,
billable: project.billable
};
}
});
}
GM_setValue('_authenticated', new Date().getTime());
GM_setValue('_api_token', resp.data.api_token);
GM_setValue('_api_url', $activeApiUrl);
GM_setValue('_default_wid', resp.data.default_wid);
GM_setValue('_clientMap', JSON.stringify($clientMap));
GM_setValue('_projectMap', JSON.stringify($projectMap));
$api_token = resp.data.api_token;
$default_wid = resp.data.default_wid;
render(selector, renderer);
} else if (!$triedAlternative) {
$triedAlternative = true;
if (apiUrl === $apiUrl) {
init(selector, renderer, $newApiUrl);
} else if (apiUrl === $newApiUrl) {
init(selector, renderer, $apiUrl);
}
} else if ($api_token) {
// Delete the API token and try again
GM_setValue('_api_token', false);
$triedAlternative = false;
init(selector, renderer, $newApiUrl);
} else {
var wrapper = document.createElement('div'),
content = createTag('div', 'content'),
link = createLink('login', 'a', 'https://new.toggl.com/', 'Login');
GM_addStyle(GM_getResourceText('togglStyle'));
link.setAttribute('target', '_blank');
wrapper.setAttribute('id', 'toggl-button-auth-failed');
content.appendChild(document.createTextNode('Authorization to your Toggl account failed!'));
content.appendChild(link);
wrapper.appendChild(content);
document.querySelector('body').appendChild(wrapper);
}
}
});
}
function render(selector, renderer) {
if (selector == null) {
return;
}
var i, len, elems = document.querySelectorAll(selector);
for (i = 0, len = elems.length; i < len; i += 1) {
elems[i].classList.add('toggl');
$instances[i] = new TogglButtonGMInstance(renderer(elems[i]));
}
document.addEventListener('TogglButtonGMUpdateStatus', function() {
GM_xmlhttpRequest({
method: "GET",
url: $activeApiUrl + "/time_entries/current",
headers: {
"Authorization": "Basic " + btoa($api_token + ':api_token')
},
onload: function (result) {
if (result.status === 200) {
var resp = JSON.parse(result.responseText),
data = resp.data || false;
if (data) {
for (i in $instances) {
$instances[i].checkCurrentLinkStatus(data);
}
}
}
}
});
});
window.addEventListener('focus', function() {
document.dispatchEvent(new CustomEvent('TogglButtonGMUpdateStatus'));
});
}
this.clickLinks = function() {
for (i in $instances) {
$instances[i].clickLink();
}
};
this.getCurrentTimeEntry = function(callback) {
GM_xmlhttpRequest({
method: "GET",
url: $activeApiUrl + "/time_entries/current",
headers: {
"Authorization": "Basic " + btoa($api_token + ':api_token')
},
onload: function (result) {
if (result.status === 200) {
var resp = JSON.parse(result.responseText),
data = resp.data || false;
if (data) {
callback(data.id, true);
}
}
}
});
};
this.stopTimeEntry = function(entryId, asCallback) {
if (entryId == null) {
if (asCallback) {
return;
}
this.getCurrentTimeEntry(this.stopTimeEntry);
return;
}
GM_xmlhttpRequest({
method: "PUT",
url: $activeApiUrl + "/time_entries/" + entryId + "/stop",
headers: {
"Authorization": "Basic " + btoa($api_token + ':api_token')
},
onload: function () {
document.dispatchEvent(new CustomEvent('TogglButtonGMUpdateStatus'));
}
});
};
function TogglButtonGMInstance(params) {
var
$curEntryId = null,
$isStarted = false,
$link = null,
$generalInfo = null,
$buttonTypeMinimal = false,
$projectSelector = window.location.host,
$projectId = null,
$projectSelected = false,
$projectSelectElem = null,
$stopCallback = null;
this.checkCurrentLinkStatus = function (data) {
var started, updateRequired = false;
if (!data) {
if ($isStarted) {
updateRequired = true;
started = false;
}
} else {
if ($generalInfo != null) {
if (!$isStarted || ($curEntryId != null && $curEntryId != data.id)) {
$curEntryId = data.id;
$isStarted = false;
}
}
if ($curEntryId == data.id) {
if (!$isStarted) {
updateRequired = true;
started = true;
}
} else {
if ($isStarted) {
updateRequired = true;
started = false;
}
}
}
if (updateRequired) {
if (!started) {
$curEntryId = null;
}
if ($link != null) {
updateLink(started);
}
if ($generalInfo != null) {
if (data) {
var projectName = 'No project',
clientName = 'No client';
if (data.pid !== undefined) {
if ($projectMap[data.pid] == undefined) {
GM_setValue('_authenticated', 0);
window.location.reload();
return;
}
projectName = $projectMap[data.pid].name;
clientName = $clientMap[$projectMap[data.pid].cid];
}
var content = createTag('div', 'content'),
contentClient = createTag('div', 'client'),
contentProject = createTag('div', 'project'),
contentDescription = createTag('div', 'description');
contentClient.innerHTML = clientName;
contentProject.innerHTML = projectName;
contentDescription.innerHTML = data.description;
content.appendChild(contentClient);
content.appendChild(contentProject);
content.appendChild(contentDescription);
while ($generalInfo.firstChild) {
$generalInfo.removeChild($generalInfo.firstChild);
}
$generalInfo.appendChild(content);
}
updateGeneralInfo(started);
}
}
};
this.clickLink = function (data) {
$link.dispatchEvent(new CustomEvent('click'));
};
createTimerLink(params);
function createTimerLink(params) {
GM_addStyle(GM_getResourceText('togglStyle'));
if (params.generalMode !== undefined && params.generalMode) {
$generalInfo = document.createElement('div');
$generalInfo.id = 'toggl-button-gi-wrapper';
$generalInfo.addEventListener('click', function (e) {
e.preventDefault();
$generalInfo.classList.toggle('collapsed');
});
document.querySelector('body').appendChild($generalInfo);
document.dispatchEvent(new CustomEvent('TogglButtonGMUpdateStatus'));
return;
}
if (params.projectIds !== undefined) {
$projectSelector += '-' + params.projectIds.join('-');
}
if (params.stopCallback !== undefined) {
$stopCallback = params.stopCallback;
}
updateProjectId();
$link = createLink('toggl-button');
$link.classList.add(params.className);
if (params.buttonType === 'minimal') {
$link.classList.add('min');
$link.removeChild($link.firstChild);
$buttonTypeMinimal = true;
}
$link.addEventListener('click', function (e) {
var opts = '';
e.preventDefault();
if ($isStarted) {
stopTimeEntry();
} else {
var billable = false;
if ($projectId != undefined && $projectId > 0) {
billable = $projectMap[$projectId].billable;
}
opts = {
$projectId: $projectId || null,
billable: billable,
description: invokeIfFunction(params.description),
createdWith: 'TogglButtonGM - ' + params.className
};
createTimeEntry(opts);
}
return false;
});
// new button created - reset state
$isStarted = false;
// check if our link is the current time entry and set the state if it is
checkCurrentTimeEntry({
$projectId: $projectId,
description: invokeIfFunction(params.description)
});
document.querySelector('body').classList.add('toggl-button-available');
if (params.targetSelectors == undefined) {
var wrapper = document.createElement('div'),
content = createTag('div', 'content');
wrapper.id = 'toggl-button-wrapper';
content.appendChild($link);
content.appendChild(createProjectSelect());
wrapper.appendChild(content);
document.querySelector('body').appendChild(wrapper);
} else {
var elem = params.targetSelectors.context || document;
if (params.targetSelectors.link != undefined) {
elem.querySelector(params.targetSelectors.link).appendChild($link);
}
if (params.targetSelectors.projectSelect != undefined) {
elem.querySelector(params.targetSelectors.projectSelect).appendChild(createProjectSelect());
}
}
return $link;
}
function createTimeEntry(timeEntry) {
var start = new Date();
GM_xmlhttpRequest({
method: "POST",
url: $activeApiUrl + "/time_entries",
headers: {
"Authorization": "Basic " + btoa($api_token + ':api_token')
},
data: JSON.stringify({
time_entry: {
start: start.toISOString(),
description: timeEntry.description,
wid: $default_wid,
pid: timeEntry.$projectId || null,
billable: timeEntry.billable || false,
duration: -(start.getTime() / 1000),
created_with: timeEntry.createdWith || 'TogglButtonGM'
}
}),
onload: function (res) {
var responseData, entryId;
responseData = JSON.parse(res.responseText);
entryId = responseData && responseData.data && responseData.data.id;
$curEntryId = entryId;
document.dispatchEvent(new CustomEvent('TogglButtonGMUpdateStatus'));
}
});
}
function checkCurrentTimeEntry(params) {
GM_xmlhttpRequest({
method: "GET",
url: $activeApiUrl + "/time_entries/current",
headers: {
"Authorization": "Basic " + btoa($api_token + ':api_token')
},
onload: function (result) {
if (result.status === 200) {
var resp = JSON.parse(result.responseText);
if (resp == null) {
return;
}
if (params.description === resp.data.description) {
$curEntryId = resp.data.id;
updateLink(true);
}
}
}
});
}
function stopTimeEntry(entryId) {
entryId = entryId || $curEntryId;
if (!entryId) {
return;
}
GM_xmlhttpRequest({
method: "PUT",
url: $activeApiUrl + "/time_entries/" + entryId + "/stop",
headers: {
"Authorization": "Basic " + btoa($api_token + ':api_token')
},
onload: function (result) {
document.dispatchEvent(new CustomEvent('TogglButtonGMUpdateStatus'));
if (result.status === 200) {
var resp = JSON.parse(result.responseText),
data = resp.data || false;
if (data) {
if ($stopCallback !== undefined) {
var currentdate = new Date();
$stopCallback((currentdate.getTime() - (data.duration * 1000)), data.duration);
}
}
}
}
});
}
function createTag(name, className, innerHTML) {
var tag = document.createElement(name);
tag.className = className;
if (innerHTML) {
tag.innerHTML = innerHTML;
}
return tag;
}
function createLink(className, tagName, linkHref, linkText) {
// Param defaults
tagName = tagName || 'a';
linkHref = linkHref || '#';
linkText = linkText || 'Start timer';
var link = createTag(tagName, className);
if (tagName === 'a') {
link.setAttribute('href', linkHref);
}
link.appendChild(document.createTextNode(linkText));
return link;
}
function updateGeneralInfo(started) {
if (started) {
$generalInfo.classList.add('active');
} else {
$generalInfo.classList.remove('active');
}
$isStarted = started;
}
function updateLink(started) {
var linkText, color = '';
if (started) {
document.querySelector('body').classList.add('toggl-button-active');
$link.classList.add('active');
color = '#1ab351';
linkText = 'Stop timer';
} else {
document.querySelector('body').classList.remove('toggl-button-active');
$link.classList.remove('active');
linkText = 'Start timer';
}
$isStarted = started;
$link.setAttribute('style', 'color:'+color+';');
if (!$buttonTypeMinimal) {
$link.innerHTML = linkText;
}
$projectSelectElem.disabled = $isStarted;
}
function updateProjectId(id) {
id = id || GM_getValue($projectSelector, 0);
$projectSelected = (id != 0);
if (id <= 0) {
$projectId = null;
}
else {
$projectId = id;
}
if ($projectSelectElem != undefined) {
$projectSelectElem.value = id;
$projectSelectElem.disabled = $isStarted;
}
GM_setValue($projectSelector, id);
if ($link != undefined) {
if ($projectSelected) {
$link.classList.remove('hidden');
}
else {
$link.classList.add('hidden');
}
}
}
function invokeIfFunction(trial) {
if (trial instanceof Function) {
return trial();
}
return trial;
}
function createProjectSelect() {
var pid,
wrapper = createTag('div', 'toggl-button-project-select'),
noneOptionAdded = false,
noneOption = document.createElement('option'),
emptyOption = document.createElement('option'),
resetOption = document.createElement('option');
$projectSelectElem = createTag('select');
// None Option to indicate that a project should be selected first
if (!$projectSelected) {
noneOption.setAttribute('value', '0');
noneOption.text = '- First select a project -';
$projectSelectElem.appendChild(noneOption);
noneOptionAdded = true;
}
// Empty Option for tasks with no project
emptyOption.setAttribute('value', '-1');
emptyOption.text = 'No Project';
$projectSelectElem.appendChild(emptyOption);
var optgroup, project, clientMap = [];
for (pid in $projectMap) {
//noinspection JSUnfilteredForInLoop
project = $projectMap[pid];
if (clientMap[project.cid] == undefined) {
optgroup = createTag('optgroup');
optgroup.label = $clientMap[project.cid];
clientMap[project.cid] = optgroup;
$projectSelectElem.appendChild(optgroup);
} else {
optgroup = clientMap[project.cid];
}
var option = document.createElement('option');
option.setAttribute('value', project.id);
option.text = project.name;
optgroup.appendChild(option);
}
// Reset Option to reload settings and projects from Toggl
resetOption.setAttribute('value', 'RESET');
resetOption.text = 'Reload settings';
$projectSelectElem.appendChild(resetOption);
$projectSelectElem.addEventListener('change', function () {
if ($projectSelectElem.value == 'RESET') {
GM_setValue('_authenticated', 0);
window.location.reload();
return;
}
if (noneOptionAdded) {
$projectSelectElem.removeChild(noneOption);
noneOptionAdded = false;
}
updateProjectId($projectSelectElem.value);
});
updateProjectId($projectId);
wrapper.appendChild($projectSelectElem);
return wrapper;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment