From 3e330663336fa5b6be0cf1a09d302e47dffc741d Mon Sep 17 00:00:00 2001 From: Stefan Walluhn Date: Fri, 21 Mar 2025 16:33:17 +0100 Subject: [PATCH 1/2] add update and delete buttons --- LICENSE | 8 +++++ public/rotate-solid.svg | 1 + public/trash-can-solid.svg | 1 + src/toggl.js | 4 +-- src/trektor.js | 30 ++++++++++------ src/trello.js | 71 +++++++++++++++++++++++++++----------- 6 files changed, 81 insertions(+), 34 deletions(-) create mode 100644 public/rotate-solid.svg create mode 100644 public/trash-can-solid.svg diff --git a/LICENSE b/LICENSE index 65d260d..cd00b40 100644 --- a/LICENSE +++ b/LICENSE @@ -19,3 +19,11 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +# Icons + +Icons published by Font-Awesome, licensed under a Creative Commons Attribution +4.0 International License; CC BY 4.0 License +(https://creativecommons.org/licenses/by/4.0/) as stated in +https://github.com/FortAwesome/Font-Awesome/blob/6.x/LICENSE.txt diff --git a/public/rotate-solid.svg b/public/rotate-solid.svg new file mode 100644 index 0000000..6e9f395 --- /dev/null +++ b/public/rotate-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/trash-can-solid.svg b/public/trash-can-solid.svg new file mode 100644 index 0000000..aff8dc1 --- /dev/null +++ b/public/trash-can-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/toggl.js b/src/toggl.js index 7a820fd..960a03d 100644 --- a/src/toggl.js +++ b/src/toggl.js @@ -91,14 +91,14 @@ export class TogglService { return togglTask; } - async track(tracking, description) { + async track(tracking) { const togglTask = await this.addTask(tracking); await this.#gateway.startTimeEntry( togglTask.workspace_id, togglTask.project_id, togglTask.id, - description, + tracking.description, ); } diff --git a/src/trektor.js b/src/trektor.js index 8a60c97..410e0ef 100644 --- a/src/trektor.js +++ b/src/trektor.js @@ -1,16 +1,24 @@ import trelloCallbacks from "./trello.js"; TrelloPowerUp.initialize({ - "card-buttons": function () { + "card-buttons": function() { return [ { icon: "./tractor-solid.svg", text: "Trek now", callback: trelloCallbacks.track, - }, + }, { + icon: "./rotate-solid.svg", + text: "Update trekking", + callback: trelloCallbacks.updateTracking, + }, { + icon: "./trash-can-solid.svg", + text: "Delete trekking", + callback: trelloCallbacks.deleteTracking, + } ]; }, - "card-badges": function (t) { + "card-badges": function(t) { return t .get("card", "shared", "tracking") .then((tracking) => @@ -19,20 +27,20 @@ TrelloPowerUp.initialize({ : [{ icon: "./tractor-solid.svg", text: `#${tracking.task}` }], ); }, - "card-detail-badges": function (t) { + "card-detail-badges": function(t) { return t.get("card", "shared", "tracking").then((tracking) => tracking === undefined ? [] : [ - { - title: "Trekking", - text: `#${tracking.task}`, - callback: trelloCallbacks.track, - }, - ], + { + title: "Trekking", + text: `#${tracking.task}`, + callback: trelloCallbacks.track, + }, + ], ); }, - "show-settings": function (t) { + "show-settings": function(t) { return t.popup({ title: "Trektor Settings", url: "./settings.html", diff --git a/src/trello.js b/src/trello.js index 2dd57ce..a9a8015 100644 --- a/src/trello.js +++ b/src/trello.js @@ -1,20 +1,21 @@ import { TogglGateway, TogglService } from "./toggl.js"; -const stripStoryPointsAndTaskToken = function (name) { +const withErrorMessage = async function(t, fnc) { + try { + await fnc(t); + } catch (error) { + t.alert({ message: error.message }); + throw error; + } +} + +const stripStoryPointsAndTaskToken = function(name) { return name .replace(/^(\s*\(\d+\))?\s*/, "") // story points, e.g. (3) .replace(/\s*#\w+\s*$/, ""); // task token, e.g. #orga_5417 }; -const track = async function (t) { - const token = await t.loadSecret("togglToken"); - if (token === null) { - throw new Error("Toggl API Token not configured"); - } - - const togglGateway = new TogglGateway(token); - const togglService = new TogglService(togglGateway); - +const extractTrackingData = async function(t) { const card = await t.card("name", "labels", "idShort", "shortLink"); const projectLabels = card.labels @@ -28,24 +29,52 @@ const track = async function (t) { } const project = projectLabels[0]; - const tracking = { + return { project, task: `${project}_${card.idShort}_${card.shortLink}`, + description: stripStoryPointsAndTaskToken(card.name), }; +} - await togglService.track(tracking, stripStoryPointsAndTaskToken(card.name)); +const setTrackingData = async function(t, tracking) { + await t.set("card", "shared", "tracking", tracking); +} - t.set("card", "shared", "tracking", tracking); - t.alert({ message: `Started trekking #${tracking.task}`}); +const track = async function(t) { + const token = await t.loadSecret("togglToken"); + if (token === null) { + throw new Error("Toggl API Token not configured"); + } + const togglService = new TogglService(new TogglGateway(token)); + + const tracking = await extractTrackingData(t); + + await togglService.track(tracking); + await setTrackingData(t, tracking); + t.alert({ message: `Started trekking #${tracking.task}` }); +}; + +const updateTracking = async function(t) { + const tracking = await extractTrackingData(t); + await setTrackingData(t, tracking); + + t.alert({ message: `Updated trekking #${tracking.task}` }); +} + +const deleteTracking = async function(t) { + t.remove("card", "shared", "tracking") + + t.alert({ message: "Deleted trekking" }); }; export default { - track: async function (t) { - try { - await track(t); - } catch (error) { - t.alert({ message: error.message }); - throw error; - } + track: async function(t) { + await withErrorMessage(t, track); + }, + updateTracking: async function(t) { + await withErrorMessage(t, updateTracking); + }, + deleteTracking: async function(t) { + await withErrorMessage(t, deleteTracking); }, }; From 408323dde29fa03875b9a8ce196ea18a6a20d227 Mon Sep 17 00:00:00 2001 From: Stefan Walluhn Date: Fri, 28 Mar 2025 18:04:19 +0100 Subject: [PATCH 2/2] hide button, needs to find better UI for update and delete --- src/trektor.js | 30 +++++++++++------------------- src/trello.js | 30 +++++++++++++++--------------- 2 files changed, 26 insertions(+), 34 deletions(-) diff --git a/src/trektor.js b/src/trektor.js index 410e0ef..8a60c97 100644 --- a/src/trektor.js +++ b/src/trektor.js @@ -1,24 +1,16 @@ import trelloCallbacks from "./trello.js"; TrelloPowerUp.initialize({ - "card-buttons": function() { + "card-buttons": function () { return [ { icon: "./tractor-solid.svg", text: "Trek now", callback: trelloCallbacks.track, - }, { - icon: "./rotate-solid.svg", - text: "Update trekking", - callback: trelloCallbacks.updateTracking, - }, { - icon: "./trash-can-solid.svg", - text: "Delete trekking", - callback: trelloCallbacks.deleteTracking, - } + }, ]; }, - "card-badges": function(t) { + "card-badges": function (t) { return t .get("card", "shared", "tracking") .then((tracking) => @@ -27,20 +19,20 @@ TrelloPowerUp.initialize({ : [{ icon: "./tractor-solid.svg", text: `#${tracking.task}` }], ); }, - "card-detail-badges": function(t) { + "card-detail-badges": function (t) { return t.get("card", "shared", "tracking").then((tracking) => tracking === undefined ? [] : [ - { - title: "Trekking", - text: `#${tracking.task}`, - callback: trelloCallbacks.track, - }, - ], + { + title: "Trekking", + text: `#${tracking.task}`, + callback: trelloCallbacks.track, + }, + ], ); }, - "show-settings": function(t) { + "show-settings": function (t) { return t.popup({ title: "Trektor Settings", url: "./settings.html", diff --git a/src/trello.js b/src/trello.js index a9a8015..5732538 100644 --- a/src/trello.js +++ b/src/trello.js @@ -1,21 +1,21 @@ import { TogglGateway, TogglService } from "./toggl.js"; -const withErrorMessage = async function(t, fnc) { +const withErrorMessage = async function (t, fnc) { try { await fnc(t); } catch (error) { t.alert({ message: error.message }); throw error; } -} +}; -const stripStoryPointsAndTaskToken = function(name) { +const stripStoryPointsAndTaskToken = function (name) { return name .replace(/^(\s*\(\d+\))?\s*/, "") // story points, e.g. (3) .replace(/\s*#\w+\s*$/, ""); // task token, e.g. #orga_5417 }; -const extractTrackingData = async function(t) { +const extractTrackingData = async function (t) { const card = await t.card("name", "labels", "idShort", "shortLink"); const projectLabels = card.labels @@ -34,13 +34,13 @@ const extractTrackingData = async function(t) { task: `${project}_${card.idShort}_${card.shortLink}`, description: stripStoryPointsAndTaskToken(card.name), }; -} +}; -const setTrackingData = async function(t, tracking) { +const setTrackingData = async function (t, tracking) { await t.set("card", "shared", "tracking", tracking); -} +}; -const track = async function(t) { +const track = async function (t) { const token = await t.loadSecret("togglToken"); if (token === null) { throw new Error("Toggl API Token not configured"); @@ -54,27 +54,27 @@ const track = async function(t) { t.alert({ message: `Started trekking #${tracking.task}` }); }; -const updateTracking = async function(t) { +const updateTracking = async function (t) { const tracking = await extractTrackingData(t); await setTrackingData(t, tracking); t.alert({ message: `Updated trekking #${tracking.task}` }); -} +}; -const deleteTracking = async function(t) { - t.remove("card", "shared", "tracking") +const deleteTracking = async function (t) { + t.remove("card", "shared", "tracking"); t.alert({ message: "Deleted trekking" }); }; export default { - track: async function(t) { + track: async function (t) { await withErrorMessage(t, track); }, - updateTracking: async function(t) { + updateTracking: async function (t) { await withErrorMessage(t, updateTracking); }, - deleteTracking: async function(t) { + deleteTracking: async function (t) { await withErrorMessage(t, deleteTracking); }, };