From d9cc66444a328dd4308afc0518d5e8edd9c2fcf3 Mon Sep 17 00:00:00 2001 From: Wendelin Date: Tue, 16 Jan 2024 15:19:01 +0100 Subject: [PATCH 1/6] merge background script and trektor.js; migrate to manifest v3 --- background.js | 76 ------------------------------------------ content_script.js | 8 ++--- manifest.json | 18 ++++------ trektor.js | 84 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 92 insertions(+), 94 deletions(-) delete mode 100644 background.js diff --git a/background.js b/background.js deleted file mode 100644 index 2b0086b..0000000 --- a/background.js +++ /dev/null @@ -1,76 +0,0 @@ -browser.runtime.onMessage.addListener(async (msg) => { - switch (msg.action) { - case 'track': - await track(...msg.args); - return; - case 'addTask': - await addTask(...msg.args); - return; - default: - throw new Error(`unknown action: ${msg.action}`); - } -}); - -async function track(cardId) { - const task = await addTask(cardId); - const card = await trektor.trelloGateway.getCard(cardId); - const cardName = stripStoryPointsAndTaskToken(card.name); - const response = await trektor.togglGateway.startTimeEntry(task.id, cardName); - return response.data; -} - -async function addTask(cardId) { - const card = await trektor.trelloGateway.getCard(cardId); - - const taskPrefixes = card.labels - .map((label) => label.name.match(/(?<=#)[a-z0-9]+$/)?.[0]) - .filter((prefix) => prefix !== undefined); - - if (taskPrefixes.length === 0) { - throw new Error('Card has no valid project labels.'); - } - if (taskPrefixes.length > 1) { - throw new Error('Card has multiple project labels.'); - } - const taskPrefix = taskPrefixes[0]; - - let taskName = card.name.match(/(?<=#)[A-Za-z0-9_-]+/)?.[0]; - - if (taskName === undefined) { - taskName = `${taskPrefix}_${card.idShort}`; - - await trektor.trelloGateway.updateCard(card.id, { - name: `${card.name} #${taskName}`, - }); - } - - const workspaces = await trektor.togglGateway.getWorkspaces(); - - if (workspaces.length === 0) { - throw new Error('Could not find any toggl workspaces.'); - } - if (workspaces.length > 1) { - throw new Error('Found multiple toggl workspaces. Not sure how to deal with that...'); - } - const allProjects = await trektor.togglGateway.getProjects(workspaces[0].id); - const projects = allProjects.filter((project) => project.name.endsWith(`(${taskPrefix})`)); - - if (projects.length === 0) { - throw new Error('Could not find any matching toggl project.'); - } - if (projects.length > 1) { - throw new Error('Found multiple matching toggl projects. Not sure how to deal with that...'); - } - const tasks = await trektor.togglGateway.getTasks(projects[0].id); - const task = tasks.find((task) => task.name === taskName); - if (task !== undefined) return task; - - const response = await trektor.togglGateway.createTask(projects[0].id, taskName) - return response.data; -} - -function stripStoryPointsAndTaskToken(cardName) { - return cardName - .replace(/^(\s*\(\d+\))?\s*/, '') // story points, e.g. (3) - .replace(/\s*#[a-z0-9_]+\s*$/, ''); // task token, e.g. #orga_5417 -} diff --git a/content_script.js b/content_script.js index 1fcd717..612fd8e 100644 --- a/content_script.js +++ b/content_script.js @@ -35,7 +35,7 @@ async function addButton() { try { await browser.runtime.sendMessage({ - action: "track", + action: 'track', args: [window.location.pathname.split("/", 3)[2]], }); trackButtonIcon.classList.replace("icon-clock", "icon-check-circle"); @@ -50,7 +50,7 @@ async function addButton() { addButton.addEventListener("click", async () => { try { await browser.runtime.sendMessage({ - action: "addTask", + action: 'addTask', args: [window.location.pathname.split("/", 3)[2]], }); } catch (err) { @@ -82,7 +82,3 @@ function awaitSelector(selector, timeout) { window.addEventListener("pushstate", () => { if (window.location.pathname.startsWith("/c/")) addButton(); }); - -window.addEventListener('load', () => { - if (window.location.pathname.startsWith("/c/")) addButton(); -}); diff --git a/manifest.json b/manifest.json index a04da4a..63dd70e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,13 +1,8 @@ { - "manifest_version": 2, + "manifest_version": 3, "name": "Trektor", "description": "Browser-Extension zum automatischen Anlegen von Toggl tracking tasks", "version": "0.0.11", - "browser_specific_settings": { - "gecko": { - "id": "trektor@aboutsource.net" - } - }, "icons": { "64": "icons/64.png" }, @@ -26,17 +21,18 @@ } ], "background": { + "service_worker": "trektor.js", "scripts": [ - "vendor/browser-polyfill.js", - "trektor.js", - "background.js" + "trektor.js" ] }, "permissions": [ - "https://api.trello.com/*", - "https://api.track.toggl.com/*", "storage" ], + "host_permissions": [ + "https://api.trello.com/*", + "https://api.track.toggl.com/*" + ], "options_ui": { "page": "options/index.html" } diff --git a/trektor.js b/trektor.js index cc5d72c..3e20fa8 100644 --- a/trektor.js +++ b/trektor.js @@ -1,3 +1,7 @@ +if (typeof browser == "undefined") { + globalThis.browser = chrome +} + class TrelloGateway { static ENDPOINT = "https://api.trello.com/1"; static API_KEY = "2379d540412e417f6f0696c1397f38a6"; @@ -95,7 +99,85 @@ class TogglGateway { } } -window.trektor = { +var trektor = { trelloGateway: new TrelloGateway(browser.storage.local), togglGateway: new TogglGateway(browser.storage.local), }; + + +browser.runtime.onMessage.addListener(async (msg) => { + switch (msg.action) { + case 'track': + await track(...msg.args); + return; + case 'addTask': + await addTask(...msg.args); + return; + default: + throw new Error(`unknown action: ${msg.action}`); + } +}); + +async function track(cardId) { + const task = await addTask(cardId); + const card = await trektor.trelloGateway.getCard(cardId); + const cardName = stripStoryPointsAndTaskToken(card.name); + const response = await trektor.togglGateway.startTimeEntry(task.id, cardName); + return response.data; +} + +async function addTask(cardId) { + const card = await trektor.trelloGateway.getCard(cardId); + + const taskPrefixes = card.labels + .map((label) => label.name.match(/(?<=#)[a-z0-9]+$/)?.[0]) + .filter((prefix) => prefix !== undefined); + + if (taskPrefixes.length === 0) { + throw new Error('Card has no valid project labels.'); + } + if (taskPrefixes.length > 1) { + throw new Error('Card has multiple project labels.'); + } + const taskPrefix = taskPrefixes[0]; + + let taskName = card.name.match(/(?<=#)[A-Za-z0-9_-]+/)?.[0]; + + if (taskName === undefined) { + taskName = `${taskPrefix}_${card.idShort}`; + + await trektor.trelloGateway.updateCard(card.id, { + name: `${card.name} #${taskName}`, + }); + } + + const workspaces = await trektor.togglGateway.getWorkspaces(); + + if (workspaces.length === 0) { + throw new Error('Could not find any toggl workspaces.'); + } + if (workspaces.length > 1) { + throw new Error('Found multiple toggl workspaces. Not sure how to deal with that...'); + } + const allProjects = await trektor.togglGateway.getProjects(workspaces[0].id); + const projects = allProjects.filter((project) => project.name.endsWith(`(${taskPrefix})`)); + + if (projects.length === 0) { + throw new Error('Could not find any matching toggl project.'); + } + if (projects.length > 1) { + throw new Error('Found multiple matching toggl projects. Not sure how to deal with that...'); + } + const tasks = await trektor.togglGateway.getTasks(projects[0].id); + const task = tasks.find((task) => task.name === taskName); + if (task !== undefined) return task; + + const response = await trektor.togglGateway.createTask(projects[0].id, taskName) + return response.data; +} + +function stripStoryPointsAndTaskToken(cardName) { + return cardName + .replace(/^(\s*\(\d+\))?\s*/, '') // story points, e.g. (3) + .replace(/\s*#[a-z0-9_]+\s*$/, ''); // task token, e.g. #orga_5417 +} From 446a5f202578fc794e9b9df73901acb258d35069 Mon Sep 17 00:00:00 2001 From: Wendelin Date: Wed, 17 Jan 2024 12:38:02 +0100 Subject: [PATCH 2/6] keep background script and trektor.js seperate; make backgroundScript a class; move scripts to seperate folder --- manifest.json | 8 +- scripts/background.js | 89 +++++++++ scripts/chromium.js | 3 + .../content_script.js | 4 + scripts/firefox.js | 1 + scripts/trektor.js | 107 ++++++++++ trektor.js | 183 ------------------ 7 files changed, 209 insertions(+), 186 deletions(-) create mode 100644 scripts/background.js create mode 100644 scripts/chromium.js rename content_script.js => scripts/content_script.js (96%) create mode 100644 scripts/firefox.js create mode 100644 scripts/trektor.js delete mode 100644 trektor.js diff --git a/manifest.json b/manifest.json index 63dd70e..44291d2 100644 --- a/manifest.json +++ b/manifest.json @@ -13,7 +13,7 @@ ], "js": [ "vendor/browser-polyfill.js", - "content_script.js" + "scripts/content_script.js" ], "css": [ "content_style.css" @@ -21,9 +21,11 @@ } ], "background": { - "service_worker": "trektor.js", + "service_worker": "scripts/chromium.js", "scripts": [ - "trektor.js" + "scripts/trektor.js", + "scripts/background.js", + "scripts/firefox.js" ] }, "permissions": [ diff --git a/scripts/background.js b/scripts/background.js new file mode 100644 index 0000000..86c137d --- /dev/null +++ b/scripts/background.js @@ -0,0 +1,89 @@ +if (typeof browser == "undefined") { + globalThis.browser = chrome +} + +class BackgroundScript { + + static trektor; + + static init(trektor) { + BackgroundScript.trektor = trektor + + browser.runtime.onMessage.addListener(async (msg) => { + switch (msg.action) { + case 'track': + await BackgroundScript.track(...msg.args); + return; + case 'addTask': + await BackgroundScript.addTask(...msg.args); + return; + default: + throw new Error(`unknown action: ${msg.action}`); + } + }); + } + + static async track(cardId) { + const task = await BackgroundScript.addTask(cardId); + const card = await BackgroundScript.trektor.trelloGateway.getCard(cardId); + const cardName = BackgroundScript.stripStoryPointsAndTaskToken(card.name); + const response = await BackgroundScript.trektor.togglGateway.startTimeEntry(task.id, cardName); + return response.data; + } + + static async addTask(cardId) { + const card = await BackgroundScript.trektor.trelloGateway.getCard(cardId); + + const taskPrefixes = card.labels + .map((label) => label.name.match(/(?<=#)[a-z0-9]+$/)?.[0]) + .filter((prefix) => prefix !== undefined); + + if (taskPrefixes.length === 0) { + throw new Error('Card has no valid project labels.'); + } + if (taskPrefixes.length > 1) { + throw new Error('Card has multiple project labels.'); + } + const taskPrefix = taskPrefixes[0]; + + let taskName = card.name.match(/(?<=#)[A-Za-z0-9_-]+/)?.[0]; + + if (taskName === undefined) { + taskName = `${taskPrefix}_${card.idShort}`; + + await BackgroundScript.trektor.trelloGateway.updateCard(card.id, { + name: `${card.name} #${taskName}`, + }); + } + + const workspaces = await BackgroundScript.trektor.togglGateway.getWorkspaces(); + + if (workspaces.length === 0) { + throw new Error('Could not find any toggl workspaces.'); + } + if (workspaces.length > 1) { + throw new Error('Found multiple toggl workspaces. Not sure how to deal with that...'); + } + const allProjects = await BackgroundScript.trektor.togglGateway.getProjects(workspaces[0].id); + const projects = allProjects.filter((project) => project.name.endsWith(`(${taskPrefix})`)); + + if (projects.length === 0) { + throw new Error('Could not find any matching toggl project.'); + } + if (projects.length > 1) { + throw new Error('Found multiple matching toggl projects. Not sure how to deal with that...'); + } + const tasks = await BackgroundScript.trektor.togglGateway.getTasks(projects[0].id); + const task = tasks.find((task) => task.name === taskName); + if (task !== undefined) return task; + + const response = await BackgroundScript.trektor.togglGateway.createTask(projects[0].id, taskName) + return response.data; + } + + static stripStoryPointsAndTaskToken(cardName) { + return cardName + .replace(/^(\s*\(\d+\))?\s*/, '') // story points, e.g. (3) + .replace(/\s*#[a-z0-9_]+\s*$/, ''); // task token, e.g. #orga_5417 + } +} diff --git a/scripts/chromium.js b/scripts/chromium.js new file mode 100644 index 0000000..7f7e853 --- /dev/null +++ b/scripts/chromium.js @@ -0,0 +1,3 @@ +importScripts('background.js', 'trektor.js'); + +BackgroundScript.init(getTrektor()); diff --git a/content_script.js b/scripts/content_script.js similarity index 96% rename from content_script.js rename to scripts/content_script.js index 612fd8e..d1c2c64 100644 --- a/content_script.js +++ b/scripts/content_script.js @@ -34,6 +34,7 @@ async function addButton() { trackButtonIcon.classList.add("trektor-state-loading"); try { + console.log("start tracking card") await browser.runtime.sendMessage({ action: 'track', args: [window.location.pathname.split("/", 3)[2]], @@ -42,6 +43,7 @@ async function addButton() { window.setTimeout(() => trackButtonIcon.classList.replace("icon-check-circle", "icon-clock"), 2000); } catch (err) { window.alert(err); + throw err; } finally { trackButtonIcon.classList.remove("trektor-state-loading"); } @@ -49,12 +51,14 @@ async function addButton() { addButton.addEventListener("click", async () => { try { + console.log("adding task") await browser.runtime.sendMessage({ action: 'addTask', args: [window.location.pathname.split("/", 3)[2]], }); } catch (err) { window.alert(err); + throw err; } }); } diff --git a/scripts/firefox.js b/scripts/firefox.js new file mode 100644 index 0000000..171a688 --- /dev/null +++ b/scripts/firefox.js @@ -0,0 +1 @@ +BackgroundScript.init(getTrektor()) diff --git a/scripts/trektor.js b/scripts/trektor.js new file mode 100644 index 0000000..7b73943 --- /dev/null +++ b/scripts/trektor.js @@ -0,0 +1,107 @@ +if (typeof browser == "undefined") { + globalThis.browser = chrome +} + +class TrelloGateway { + static ENDPOINT = "https://api.trello.com/1"; + static API_KEY = "2379d540412e417f6f0696c1397f38a6"; + + #storage; + + constructor(storage) { + this.#storage = storage; + } + + getCard(id) { + return this.#request("get", `/cards/${id}`); + } + + updateCard(id, data) { + return this.#request("put", `/cards/${id}`, data); + } + + async #request(method, path, data = null) { + const url = this.constructor.ENDPOINT + path; + const { trello: token } = await this.#storage.get("trello"); + + const response = await fetch(url, { + method, + headers: { + "Authorization": `OAuth oauth_consumer_key="${this.constructor.API_KEY}", oauth_token="${token}"`, + "Content-Type": "application/json; charset=utf-8", + }, + body: (data === null) ? null : JSON.stringify(data), + }); + + if (response.status === 401) { + throw new Error('Invalid or expired trello token.'); + } else { + return response.json(); + } + } +} + +class TogglGateway { + static ENDPOINT = "https://api.track.toggl.com/api/v8"; + + #storage; + + constructor(storage) { + this.#storage = storage; + } + + getWorkspaces() { + return this.#request("get", "/workspaces"); + } + + getProjects(workspaceId) { + return this.#request("get", `/workspaces/${workspaceId}/projects`); + } + + getTasks(projectId) { + return this.#request("get", `/projects/${projectId}/tasks`); + } + + createTask(projectId, name) { + return this.#request("post", "/tasks", { + task: { name, pid: projectId }, + }); + } + + getCurrentTimeEntry() { + return this.#request("get", "/time_entries/current"); + } + + startTimeEntry(taskId, description) { + return this.#request("post", "/time_entries/start", { + time_entry: { description, tid: taskId, created_with: "trektor" }, + }); + } + + async #request(method, path, data = null) { + const url = this.constructor.ENDPOINT + path; + const { toggl: token } = await this.#storage.get("toggl"); + + const response = await fetch(url, { + method, + headers: { + "Authorization": `Basic ${btoa(`${token}:api_token`)}`, + "Content-Type": "application/json; charset=utf-8", + }, + body: (data === null) ? null : JSON.stringify(data), + }); + + if (response.status === 403) { + throw new Error('Invalid toggl token.'); + } else { + return response.json(); + } + } +} + +function getTrektor() { + return { + trelloGateway: new TrelloGateway(browser.storage.local), + togglGateway: new TogglGateway(browser.storage.local), + } +} \ No newline at end of file diff --git a/trektor.js b/trektor.js deleted file mode 100644 index 3e20fa8..0000000 --- a/trektor.js +++ /dev/null @@ -1,183 +0,0 @@ -if (typeof browser == "undefined") { - globalThis.browser = chrome -} - -class TrelloGateway { - static ENDPOINT = "https://api.trello.com/1"; - static API_KEY = "2379d540412e417f6f0696c1397f38a6"; - - #storage; - - constructor(storage) { - this.#storage = storage; - } - - getCard(id) { - return this.#request("get", `/cards/${id}`); - } - - updateCard(id, data) { - return this.#request("put", `/cards/${id}`, data); - } - - async #request(method, path, data = null) { - const url = this.constructor.ENDPOINT + path; - const { trello: token } = await this.#storage.get("trello"); - - const response = await fetch(url, { - method, - headers: { - "Authorization": `OAuth oauth_consumer_key="${this.constructor.API_KEY}", oauth_token="${token}"`, - "Content-Type": "application/json; charset=utf-8", - }, - body: (data === null) ? null : JSON.stringify(data), - }); - - if (response.status === 401) { - throw new Error('Invalid or expired trello token.'); - } else { - return response.json(); - } - } -} - -class TogglGateway { - static ENDPOINT = "https://api.track.toggl.com/api/v8"; - - #storage; - - constructor(storage) { - this.#storage = storage; - } - - getWorkspaces() { - return this.#request("get", "/workspaces"); - } - - getProjects(workspaceId) { - return this.#request("get", `/workspaces/${workspaceId}/projects`); - } - - getTasks(projectId) { - return this.#request("get", `/projects/${projectId}/tasks`); - } - - createTask(projectId, name) { - return this.#request("post", "/tasks", { - task: { name, pid: projectId }, - }); - } - - getCurrentTimeEntry() { - return this.#request("get", "/time_entries/current"); - } - - startTimeEntry(taskId, description) { - return this.#request("post", "/time_entries/start", { - time_entry: { description, tid: taskId, created_with: "trektor" }, - }); - } - - async #request(method, path, data = null) { - const url = this.constructor.ENDPOINT + path; - const { toggl: token } = await this.#storage.get("toggl"); - - const response = await fetch(url, { - method, - headers: { - "Authorization": `Basic ${btoa(`${token}:api_token`)}`, - "Content-Type": "application/json; charset=utf-8", - }, - body: (data === null) ? null : JSON.stringify(data), - }); - - if (response.status === 403) { - throw new Error('Invalid toggl token.'); - } else { - return response.json(); - } - } -} - -var trektor = { - trelloGateway: new TrelloGateway(browser.storage.local), - togglGateway: new TogglGateway(browser.storage.local), -}; - - -browser.runtime.onMessage.addListener(async (msg) => { - switch (msg.action) { - case 'track': - await track(...msg.args); - return; - case 'addTask': - await addTask(...msg.args); - return; - default: - throw new Error(`unknown action: ${msg.action}`); - } -}); - -async function track(cardId) { - const task = await addTask(cardId); - const card = await trektor.trelloGateway.getCard(cardId); - const cardName = stripStoryPointsAndTaskToken(card.name); - const response = await trektor.togglGateway.startTimeEntry(task.id, cardName); - return response.data; -} - -async function addTask(cardId) { - const card = await trektor.trelloGateway.getCard(cardId); - - const taskPrefixes = card.labels - .map((label) => label.name.match(/(?<=#)[a-z0-9]+$/)?.[0]) - .filter((prefix) => prefix !== undefined); - - if (taskPrefixes.length === 0) { - throw new Error('Card has no valid project labels.'); - } - if (taskPrefixes.length > 1) { - throw new Error('Card has multiple project labels.'); - } - const taskPrefix = taskPrefixes[0]; - - let taskName = card.name.match(/(?<=#)[A-Za-z0-9_-]+/)?.[0]; - - if (taskName === undefined) { - taskName = `${taskPrefix}_${card.idShort}`; - - await trektor.trelloGateway.updateCard(card.id, { - name: `${card.name} #${taskName}`, - }); - } - - const workspaces = await trektor.togglGateway.getWorkspaces(); - - if (workspaces.length === 0) { - throw new Error('Could not find any toggl workspaces.'); - } - if (workspaces.length > 1) { - throw new Error('Found multiple toggl workspaces. Not sure how to deal with that...'); - } - const allProjects = await trektor.togglGateway.getProjects(workspaces[0].id); - const projects = allProjects.filter((project) => project.name.endsWith(`(${taskPrefix})`)); - - if (projects.length === 0) { - throw new Error('Could not find any matching toggl project.'); - } - if (projects.length > 1) { - throw new Error('Found multiple matching toggl projects. Not sure how to deal with that...'); - } - const tasks = await trektor.togglGateway.getTasks(projects[0].id); - const task = tasks.find((task) => task.name === taskName); - if (task !== undefined) return task; - - const response = await trektor.togglGateway.createTask(projects[0].id, taskName) - return response.data; -} - -function stripStoryPointsAndTaskToken(cardName) { - return cardName - .replace(/^(\s*\(\d+\))?\s*/, '') // story points, e.g. (3) - .replace(/\s*#[a-z0-9_]+\s*$/, ''); // task token, e.g. #orga_5417 -} From c7e438bd927cdeb24aa97c63a35a3214a2c33e6f Mon Sep 17 00:00:00 2001 From: Wendelin Date: Thu, 18 Jan 2024 11:21:37 +0100 Subject: [PATCH 3/6] switch from shortId to shortLink for task name generation --- scripts/background.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/background.js b/scripts/background.js index 86c137d..61d1a6b 100644 --- a/scripts/background.js +++ b/scripts/background.js @@ -49,7 +49,7 @@ class BackgroundScript { let taskName = card.name.match(/(?<=#)[A-Za-z0-9_-]+/)?.[0]; if (taskName === undefined) { - taskName = `${taskPrefix}_${card.idShort}`; + taskName = `${taskPrefix}_${card.shortLink}`; await BackgroundScript.trektor.trelloGateway.updateCard(card.id, { name: `${card.name} #${taskName}`, From d4df38cf469440d45564bcfa85f2e7b70db9093d Mon Sep 17 00:00:00 2001 From: Wendelin Date: Thu, 18 Jan 2024 11:59:25 +0100 Subject: [PATCH 4/6] switch from shortUrl to card id + board id --- scripts/background.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/background.js b/scripts/background.js index 61d1a6b..377eaa8 100644 --- a/scripts/background.js +++ b/scripts/background.js @@ -49,7 +49,8 @@ class BackgroundScript { let taskName = card.name.match(/(?<=#)[A-Za-z0-9_-]+/)?.[0]; if (taskName === undefined) { - taskName = `${taskPrefix}_${card.shortLink}`; + console.log(card.idBoard) + taskName = `${taskPrefix}_${card.idShort}_${card.idBoard.substring(0, 3)}`; await BackgroundScript.trektor.trelloGateway.updateCard(card.id, { name: `${card.name} #${taskName}`, From 243bb07c97f32f1e11a7b8b209c93aa0d8930f6f Mon Sep 17 00:00:00 2001 From: Wendelin Date: Thu, 18 Jan 2024 12:04:34 +0100 Subject: [PATCH 5/6] remove debug log --- scripts/background.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/background.js b/scripts/background.js index 377eaa8..30906bd 100644 --- a/scripts/background.js +++ b/scripts/background.js @@ -49,7 +49,6 @@ class BackgroundScript { let taskName = card.name.match(/(?<=#)[A-Za-z0-9_-]+/)?.[0]; if (taskName === undefined) { - console.log(card.idBoard) taskName = `${taskPrefix}_${card.idShort}_${card.idBoard.substring(0, 3)}`; await BackgroundScript.trektor.trelloGateway.updateCard(card.id, { From 3a2cb772ac9205feeee7fee0265b7fe8c763144e Mon Sep 17 00:00:00 2001 From: Wendelin Date: Tue, 23 Jan 2024 12:02:36 +0100 Subject: [PATCH 6/6] use card id plus short link --- scripts/background.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/background.js b/scripts/background.js index 30906bd..aa9fd21 100644 --- a/scripts/background.js +++ b/scripts/background.js @@ -49,7 +49,7 @@ class BackgroundScript { let taskName = card.name.match(/(?<=#)[A-Za-z0-9_-]+/)?.[0]; if (taskName === undefined) { - taskName = `${taskPrefix}_${card.idShort}_${card.idBoard.substring(0, 3)}`; + taskName = `${taskPrefix}_${card.idShort}_${card.shortLink}`; await BackgroundScript.trektor.trelloGateway.updateCard(card.id, { name: `${card.name} #${taskName}`,