diff --git a/src/extract.js b/src/extract.js new file mode 100644 index 0000000..f4602ba --- /dev/null +++ b/src/extract.js @@ -0,0 +1,44 @@ +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 extractProjectFromLabels = function (labels) { + const projectLabels = labels + .map((label) => label.name.match(/(?<=#)[a-z0-9]+$/)?.[0]) + .filter((prefix) => prefix !== undefined); + if (projectLabels.length === 0) { + throw new Error("Card has no valid project labels."); + } + if (projectLabels.length > 1) { + throw new Error("Card has multiple project labels."); + } + return projectLabels[0]; +}; + +const extractTaskFromLabels = function (labels) { + const tasks = labels + .map((label) => label.name.match(/(?<=!)\w+$/)?.[0]) + .filter((prefix) => prefix !== undefined); + if (tasks.length === 0) { + return null; + } + if (tasks.length > 1) { + throw new Error("Card has multiple tasks labels."); + } + return tasks[0]; +}; + +export const extractTrackingData = async function (t) { + const card = await t.card("name", "labels", "idShort", "shortLink"); + const project = extractProjectFromLabels(card.labels); + + return { + project, + task: + extractTaskFromLabels(card.labels) ?? + `${project}_${card.idShort}_${card.shortLink}`, + description: stripStoryPointsAndTaskToken(card.name), + }; +}; diff --git a/src/trello.js b/src/trello.js index 5732538..b7a5878 100644 --- a/src/trello.js +++ b/src/trello.js @@ -1,4 +1,5 @@ import { TogglGateway, TogglService } from "./toggl.js"; +import { extractTrackingData } from "./extract.js"; const withErrorMessage = async function (t, fnc) { try { @@ -9,33 +10,6 @@ const withErrorMessage = async function (t, fnc) { } }; -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 card = await t.card("name", "labels", "idShort", "shortLink"); - - const projectLabels = card.labels - .map((label) => label.name.match(/(?<=#)[a-z0-9]+$/)?.[0]) - .filter((prefix) => prefix !== undefined); - if (projectLabels.length === 0) { - throw new Error("Card has no valid project labels."); - } - if (projectLabels.length > 1) { - throw new Error("Card has multiple project labels."); - } - const project = projectLabels[0]; - - return { - project, - task: `${project}_${card.idShort}_${card.shortLink}`, - description: stripStoryPointsAndTaskToken(card.name), - }; -}; - const setTrackingData = async function (t, tracking) { await t.set("card", "shared", "tracking", tracking); };