Skip to content

Commit

Permalink
Merge pull request #10 from Involve-Digital/asana-api-implementation
Browse files Browse the repository at this point in the history
Asana api implementation
  • Loading branch information
kuba65 authored Nov 5, 2024
2 parents 83e9236 + cbc407c commit b22f2d3
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 35 deletions.
49 changes: 49 additions & 0 deletions icons/loader.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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": 3,
"name": "Asana task name extension",
"description": "Asana task name extension",
"version": "2.0",
"version": "2.1",
"permissions": ["clipboardWrite", "storage"],
"action": {
"default_popup": "/popup/hello.html",
Expand Down Expand Up @@ -32,7 +32,8 @@
"/icons/cross.svg",
"/icons/start.svg",
"/icons/start-cr.svg",
"/icons/analysis.svg"
"/icons/analysis.svg",
"/icons/loader.svg"
]
}
],
Expand Down
4 changes: 4 additions & 0 deletions popup/hello.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ <h1 class="title">Asana task name</h1>
<label for="togglApiKey">Toggl Api key</label>
<input type="text" id="togglApiKey">
</li>
<li>
<label for="asanaApiKey">Asana Api key</label>
<input type="text" id="asanaApiKey">
</li>
<li>
<label for="copyButton">Button - task name</label>
<input type="checkbox" id="copyButton">
Expand Down
8 changes: 8 additions & 0 deletions popup/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ document.addEventListener("DOMContentLoaded", function () {
}
});

chrome.storage.sync.get("asanaApiKey", function (data) {
if (data.asanaApiKey) {
document.getElementById("asanaApiKey").value = data.asanaApiKey;
}
});

chrome.storage.sync.get("copyButton", function (data) {
if (data.copyButton) {
document.getElementById("copyButton").checked = data.copyButton;
Expand All @@ -31,13 +37,15 @@ document.addEventListener("DOMContentLoaded", function () {

document.getElementById("save").addEventListener("click", function () {
const togglApiKey = document.getElementById("togglApiKey").value;
const asanaApiKey = document.getElementById("asanaApiKey").value;
const copyButton = document.getElementById("copyButton").checked;
const togglReportButton = document.getElementById("togglReportButton").checked;
const trackingButton = document.getElementById("trackingButton").checked;
const crTrackingButton = document.getElementById("crTrackingButton").checked;

chrome.storage.sync.set({
"togglApiKey": togglApiKey,
"asanaApiKey": asanaApiKey,
"copyButton": copyButton,
"togglReportButton": togglReportButton,
"trackingButton": trackingButton,
Expand Down
152 changes: 119 additions & 33 deletions scripts/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ const TASK_TITLE_SELECTOR = 'textarea.BaseTextarea.simpleTextarea--dynamic.simpl
const PARENT_TASK_TITLE_SELECTOR = 'div.Breadcrumb.TaskAncestryBreadcrumb.TaskAncestry-taskAncestryBreadcrumb > a';
const HEADING_SELECTOR = 'div.TaskPaneToolbar.TaskPane-header.Stack.Stack--align-center.Stack--direction-row.Stack--display-block.Stack--justify-space-between';
const ALL_COMMENTS_SELECTOR = 'div.FeedBlockStory.TaskStoryFeed-blockStory';
const COMMENT_TEXT_DIV_SELECTOR = 'div.TypographyPresentation.TypographyPresentation--m.RichText3-paragraph--withVSpacingNormal.RichText3-paragraph';
const COMMENT_TEXT_DIV_SELECTOR = 'div.TypographyPresentation.TypographyPresentation--medium.RichText3-paragraph--withVSpacingNormal.RichText3-paragraph';
const COMMENT_BUTTON_DIV_SELECTOR = 'div.ThemeableIconButtonPresentation--isEnabled.ThemeableIconButtonPresentation.ThemeableIconButtonPresentation--medium.SubtleIconButton--standardTheme.SubtleIconButton.BlockStoryDropdown.FeedBlockStory-actionsDropdownButton';
const PIN_TO_TOP_BUTTON_SELECTOR = '.TypographyPresentation.TypographyPresentation--overflowTruncate.TypographyPresentation--m.LeftIconItemStructure-label';
const PIN_TO_TOP_BUTTON_SELECTOR = '.TypographyPresentation.TypographyPresentation--overflowTruncate.TypographyPresentation--medium.LeftIconItemStructure-label';
const COMMENT_SECTION_CLASS_NAME = 'TaskStoryFeed';
const MR_DELIMITERS = ['MR: ', 'MR - '];
const COPY_BUTTON_ID = 'asana-task-name-extension-copy-button';
Expand All @@ -13,14 +13,20 @@ const START_TRACKING_BUTTON_ID = 'asana-task-name-extension-start-tracking-butto
const START_CODE_REVIEW_TRACKING_BUTTON_ID = 'asana-task-name-extension-start-code-review-tracking-button';
const TASK_PROJECT_SELECTOR = 'div.TaskProjectTokenPill-name';
const TASK_PROJECT_FALLBACK_SELECTOR = 'a.HiddenNavigationLink.TaskAncestry-ancestorProject';
const COPY_TASK_LINK_SELECTOR = 'div.TaskPaneToolbar-copyLinkButton';
const BASE_API_URL = 'https://backend.involve.cz/api/v1';
const TOGGL_REPORT_URL = 'https://track.toggl.com/reports/summary/1033184/description/__taskName__/period/last12Months';


const ICONS_TO_BUTTON = {
[COPY_BUTTON_ID]: 'copy',
[START_TRACKING_BUTTON_ID]: 'start',
[START_CODE_REVIEW_TRACKING_BUTTON_ID]: 'start-cr',
}

function getSvgIcon(name) {
const svgPath = chrome.runtime.getURL('icons/' + name + '.svg');

console.log(svgPath);

return fetch(svgPath)
.then(response => response.text())
.catch(error => {
Expand All @@ -45,6 +51,23 @@ const handleRunTracking = (apiKey, taskName, project, tags) => {
}).catch(err => console.error(err));
};

const getTaskInfo = async (apiKey, taskId) => {
const response = await fetch(BASE_API_URL + '/asana-extension/task-information', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
apiKey,
taskId,
})
});

const jsonResponse = await response.json();

return jsonResponse?.data
};

function extractTaskInfo(onlyChildTask) {
const taskTitleElement = document.querySelector(TASK_TITLE_SELECTOR);
const parentTaskElements = document.querySelectorAll(PARENT_TASK_TITLE_SELECTOR);
Expand Down Expand Up @@ -93,39 +116,102 @@ chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
}
});

const copyTaskInfo = (shiftPressed, startTracking = false, tags = []) => {
const taskInfo = extractTaskInfo(shiftPressed);
const button = document.getElementById(COPY_BUTTON_ID);

if (taskInfo && startTracking) {
chrome.storage.sync.get('togglApiKey', function (data) {
if (data.togglApiKey) {
const project = extractTaskProjectName();
handleRunTracking(data.togglApiKey, taskInfo, project, tags);
const fetchData = async (taskId) => {
return new Promise((resolve, reject) => {
chrome.storage.sync.get('asanaApiKey', async function (data) {
if (data.asanaApiKey) {
try {
const taskInfo = await getTaskInfo(
data.asanaApiKey,
taskId
);
resolve(taskInfo);
} catch (error) {
reject(error);
}
} else {
reject('API Key not found');
}
});
});
};

const copyTaskInfo = async (shiftPressed, startTracking = false, tags = [], buttonId = null) => {
const copyButton = document.querySelector(COPY_TASK_LINK_SELECTOR);
copyButton.click();
let link;

try {
const clipboardContents = await navigator.clipboard.read();

if (!clipboardContents.length){
return;
}

const blob = await clipboardContents[0].getType("text/plain");
link = await blob.text();
} catch (error) {
console.error(error); // Log any errors that occur

return;
}

if (taskInfo) {
navigator.clipboard.writeText(taskInfo)
.then(async () => {
button.innerHTML = await getSvgIcon('check');
const urlParts = link?.replace('/f', '').split('/');
let taskId;

setTimeout(async function () {
button.innerHTML = await getSvgIcon('copy');
}, 5000);
if (!urlParts || !urlParts.length) {
return;
}

taskId = urlParts.pop();

const button = document.getElementById(buttonId || COPY_BUTTON_ID);

console.log('Task info copied to clipboard:', taskInfo);
})
.catch(async err => {
button.innerHTML = await getSvgIcon('cross');
try {
button.innerHTML = await getSvgIcon('loader');

setTimeout(async function () {
button.innerHTML = await getSvgIcon('copy');
}, 5000);
const taskInfoApi = await fetchData(taskId);
let taskInfo;

if (shiftPressed) {
taskInfo = taskInfoApi?.taskName
} else {
taskInfo = taskInfoApi?.wholeTaskName;
}

console.error('Failed to copy task info to clipboard:', err);
if (taskInfoApi && startTracking) {
chrome.storage.sync.get('togglApiKey', function (data) {
if (data.togglApiKey) {
const project = taskInfoApi.project;
const taskInfo = taskInfoApi.wholeTaskName;
handleRunTracking(data.togglApiKey, taskInfo, project, tags);
}
});
}

if (taskInfo) {
navigator.clipboard.writeText(taskInfo)
.then(async () => {
button.innerHTML = await getSvgIcon('check');

console.log('Task info copied to clipboard:', taskInfo);
})
.catch(async err => {
button.innerHTML = await getSvgIcon('cross');

console.error('Failed to copy task info to clipboard:', err);
})
.finally(() => {
setTimeout(async function () {
const iconName = ICONS_TO_BUTTON[button.id];
button.innerHTML = await getSvgIcon(iconName);
}, 5000);
});
}
} catch (error) {
const iconName = ICONS_TO_BUTTON[button.id];
button.innerHTML = await getSvgIcon(iconName);
console.error(error); // Log any errors that occur
}
};

Expand All @@ -137,7 +223,7 @@ const appendCopyButton = async (elementToAppendButton) => {
elementToAppendButton,
COPY_BUTTON_ID,
await getSvgIcon('copy'),
(e) => copyTaskInfo(e.shiftKey),
(e) => copyTaskInfo(e.shiftKey, false, [], COPY_BUTTON_ID),
'Copy task name',
);
}
Expand Down Expand Up @@ -172,24 +258,24 @@ const appendTrackingButtons = (elementToAppendButton) => {
chrome.storage.sync.get('togglApiKey', async function (data) {
if (data.togglApiKey) {
chrome.storage.sync.get('trackingButton', async function (data) {
if (data.trackingButton){
if (data.trackingButton) {
appendButton(
elementToAppendButton,
START_TRACKING_BUTTON_ID,
await getSvgIcon('start'),
(e) => copyTaskInfo(e.shiftKey, true),
(e) => copyTaskInfo(e.shiftKey, true, [], START_TRACKING_BUTTON_ID),
'Start tracking',
);
}
});

chrome.storage.sync.get('crTrackingButton', async function (data) {
if (data.crTrackingButton){
if (data.crTrackingButton) {
appendButton(
elementToAppendButton,
START_CODE_REVIEW_TRACKING_BUTTON_ID,
await getSvgIcon('start-cr'),
(e) => copyTaskInfo(e.shiftKey, true, ['code review']),
(e) => copyTaskInfo(e.shiftKey, true, ['code review'], START_CODE_REVIEW_TRACKING_BUTTON_ID),
'Start Code review tracking',
);
}
Expand Down

0 comments on commit b22f2d3

Please sign in to comment.