Skip to content
This repository was archived by the owner on Nov 11, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
web-ext-artifacts
node_modules
2 changes: 1 addition & 1 deletion background.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
trektor.runtime.onMessage.addListener(async (msg) => {
browser.runtime.onMessage.addListener(async (msg) => {
switch (msg.action) {
case 'track':
await track(...msg.args);
Expand Down
28 changes: 15 additions & 13 deletions content_script.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,29 @@ async function addButton() {
trackButton.addEventListener("click", async () => {
trackButtonIcon.classList.add("trektor-state-loading");

const response = await trektor.runtime.sendMessage({
try {
const response = await browser.runtime.sendMessage({
action: "track",
args: [window.location.pathname.split("/", 3)[2]],
});
trackButtonIcon.classList.remove("trektor-state-loading");

if (response) {
window.alert(response);
} else {
});
trackButtonIcon.classList.replace("icon-clock", "icon-check-circle");
window.setTimeout(() => trackButtonIcon.classList.replace("icon-check-circle", "icon-clock"), 2000);
} catch (err) {
window.alert(err);
} finally {
trackButtonIcon.classList.remove("trektor-state-loading");
}
});

addButton.addEventListener("click", async () => {
const response = await trektor.runtime.sendMessage({
action: "addTask",
args: [window.location.pathname.split("/", 3)[2]],
});

if (response) window.alert(response);
try {
const response = await browser.runtime.sendMessage({
action: "addTask",
args: [window.location.pathname.split("/", 3)[2]],
});
} catch (err) {
window.alert(err);
}
});
}

Expand Down
5 changes: 3 additions & 2 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "Trektor",
"description": "Browser-Extension zum automatischen Anlegen von Toggl tracking tasks",
"version": "0.0.3",
"version": "0.0.10",
"browser_specific_settings": {
"gecko": {
"id": "trektor@aboutsource.net"
Expand All @@ -17,7 +17,7 @@
"https://trello.com/*"
],
"js": [
"trektor.js",
"vendor/browser-polyfill.js",
"content_script.js"
],
"css": [
Expand All @@ -27,6 +27,7 @@
],
"background": {
"scripts": [
"vendor/browser-polyfill.js",
"trektor.js",
"background.js"
]
Expand Down
4 changes: 2 additions & 2 deletions options/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</style>
</head>
<body>
<a href="https://trello.com/1/authorize?expiration=90days&scope=read,write&response_type=token&name=Trektor&key=afadffe77f745496f80ebb4bf460c615" target="_blank">
<a href="https://trello.com/1/authorize?expiration=30days&scope=read,write&response_type=token&name=Trektor&key=2379d540412e417f6f0696c1397f38a6" target="_blank">
Trello Token
</a>

Expand All @@ -29,7 +29,7 @@

<input type="text" name="toggl" />

<script src="../trektor.js"></script>
<script src="../vendor/browser-polyfill.js"></script>
<script src="./script.js"></script>
</body>
</html>
4 changes: 2 additions & 2 deletions options/script.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
document.querySelectorAll("input").forEach((field) => {
field.addEventListener("input", (e) => {
trektor.storage.set({ [e.target.name]: e.target.value });
browser.storage.local.set({ [e.target.name]: e.target.value });
});

trektor.storage.get(field.name).then(({ [field.name]: value }) => {
browser.storage.local.get(field.name).then(({ [field.name]: value }) => {
field.value = (value === undefined) ? '' : value;
});
});
13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "trektor",
"private": true,
"repository": "git@github.com:aboutsource/trektor",
"author": "info@aboutsource.net",
"license": "MIT",
"scripts": {
"postinstall": "cp node_modules/webextension-polyfill/dist/browser-polyfill.js vendor/browser-polyfill.js"
},
"dependencies": {
"webextension-polyfill": "^0.8.0"
}
}
97 changes: 26 additions & 71 deletions trektor.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,24 @@
class ChromeStorage {
constructor(storage) {
this.storage = storage;
}
get(keys) {
return new Promise((resolve) => {
this.storage.get(keys, resolve);
})
}
set(values) {
return new Promise((resolve) => {
this.storage.set(values, resolve);
})
}
}

class ChromeRuntime {
constructor(runtime) {
this.runtime = runtime;
}

sendMessage(msg) {
return new Promise((resolve) => {
this.runtime.sendMessage(msg, resolve);
});
}

get onMessage() {
const runtime = this.runtime;

return {
addListener(callback) {
runtime.onMessage.addListener((msg, sender, respond) => {
callback(msg)
.then((response) => { respond(response) })
.catch((error) => respond(error.message));
return true;
});
},
}
}
}

class TrelloGateway {
static ENDPOINT = "https://api.trello.com/1";
static API_KEY = "afadffe77f745496f80ebb4bf460c615";
static API_KEY = "2379d540412e417f6f0696c1397f38a6";

#storage;

constructor(storage) {
this.storage = storage;
this.#storage = storage;
}

getCard(id) {
return this.request("get", `/cards/${id}`);
return this.#request("get", `/cards/${id}`);
}

updateCard(id, data) {
return this.request("put", `/cards/${id}`, data);
return this.#request("put", `/cards/${id}`, data);
}

async request(method, path, data = null) {
async #request(method, path, data = null) {
const url = this.constructor.ENDPOINT + path;
const { trello: token } = await this.storage.get("trello");
const { trello: token } = await this.#storage.get("trello");

const response = await fetch(url, {
method,
Expand All @@ -81,37 +40,43 @@ class TrelloGateway {
class TogglGateway {
static ENDPOINT = "https://api.track.toggl.com/api/v8";

#storage;

constructor(storage) {
this.storage = storage;
this.#storage = storage;
}

getWorkspaces() {
return this.request("get", "/workspaces");
return this.#request("get", "/workspaces");
}

getProjects(workspaceId) {
return this.request("get", `/workspaces/${workspaceId}/projects`);
return this.#request("get", `/workspaces/${workspaceId}/projects`);
}

getTasks(projectId) {
return this.request("get", `/projects/${projectId}/tasks`);
return this.#request("get", `/projects/${projectId}/tasks`);
}

createTask(projectId, name) {
return this.request("post", "/tasks", {
return this.#request("post", "/tasks", {
task: { name, pid: projectId },
});
}

getCurrentTimeEntry() {
return this.#request("get", "/time_entries/current");
}

startTimeEntry(taskId) {
return this.request("post", "/time_entries/start", {
return this.#request("post", "/time_entries/start", {
time_entry: { tid: taskId, created_with: "trektor" },
});
}

async request(method, path, data = null) {
async #request(method, path, data = null) {
const url = this.constructor.ENDPOINT + path;
const { toggl: token } = await this.storage.get("toggl");
const { toggl: token } = await this.#storage.get("toggl");

const response = await fetch(url, {
method,
Expand All @@ -130,17 +95,7 @@ class TogglGateway {
}
}

const trektor = {};

if (window.chrome !== undefined) {
trektor.storage = new ChromeStorage(chrome.storage.local);
trektor.runtime = new ChromeRuntime(chrome.runtime);
} else {
trektor.storage = browser.storage.local;
trektor.runtime = browser.runtime;
}

trektor.trelloGateway = new TrelloGateway(trektor.storage);
trektor.togglGateway = new TogglGateway(trektor.storage);

window.trektor = trektor;
window.trektor = {
trelloGateway: new TrelloGateway(browser.storage.local),
togglGateway: new TogglGateway(browser.storage.local),
};
Loading