Skip to content

Instantly share code, notes, and snippets.

@rztprog
Last active April 29, 2024 14:21
Show Gist options
  • Save rztprog/9b9db9c372f440cf792cbe3ab333c4be to your computer and use it in GitHub Desktop.
Save rztprog/9b9db9c372f440cf792cbe3ab333c4be to your computer and use it in GitHub Desktop.
Tampermonkey - Automate ClickUp git branch command on each card for Repozen dev environment
// ==UserScript==
// @name Repozen Clickup Branch
// @namespace http://github.com/rztprog
// @version 0.8
// @description Automate ClickUp git branch command on each card for Repozen dev environment
// @author Rztprog
// @match https://app.clickup.com/*
// @icon https://i.imgur.com/2W0K5dQ.png
// @grant none
// ==/UserScript==
(function() {
'use strict';
let timer = null;
let taskInfo = null;
let cardTitle = null;
let commandParagraph = null;
const checkCards = () => {
if (document.querySelectorAll(".cu-panel-board__task").length !== 0) {
clearInterval(timer);
mutations();
}
}
timer = setInterval(checkCards, 500);
const handleCardClick = () => {
let counter = 0;
const checkAttributes = () => {
taskInfo = document.querySelector(".task-column__body-toolbar");
cardTitle = document.title.substring(0, document.title.lastIndexOf('|')).trim();
commandParagraph = document.querySelector(".repozenCommand");
if (cardTitle && taskInfo && !commandParagraph) {
taskInfo.insertAdjacentElement('afterend', newDiv(cardTitle));
titleTrigger();
clearInterval(timer);
} else if (counter > 10) {
clearInterval(timer);
}
counter++;
}
clearInterval(timer); // Prevent duplication and loop
timer = setInterval(checkAttributes, 500);
}
const titleTrigger = () => {
const taskNameTextarea = document.querySelector("textarea[aria-label='Modifier le nom de la tâche']");
const updateNewParagraph = () => {
const updatedCommand = formattedCommand(document.title.substring(0, document.title.lastIndexOf('|')).trim());
commandParagraph = document.querySelector(".repozenCommand");
commandParagraph.innerText = updatedCommand;
commandParagraph.addEventListener('click', () => {
copyToClipboard(updatedCommand, commandParagraph);
});
};
taskNameTextarea.addEventListener("blur", updateNewParagraph);
}
const newDiv = (taskName) => {
const newDiv = document.createElement('div');
const styles = {
display: 'flex',
margin: '10px 9px 0 0',
position: 'sticky',
zIndex: '106',
top: '10px',
}
Object.assign(newDiv.style, styles);
newDiv.appendChild(newParagraph(formattedCommand(taskName)));
newDiv.appendChild(cardIdButton());
adaptTaskNameBlock();
return newDiv;
}
const newParagraph = (formattedCommand) => {
const newP = document.createElement('p');
const styles = {
backgroundColor: '#ccc',
color: 'black',
padding: '10px',
fontSize: '18px',
textAlign: 'center',
cursor: 'pointer',
transition: 'background-color 0.3s',
width: '80%',
borderRight: '1px solid #555',
margin: '0 0 0 20px',
borderRadius: '4px 0 0 4px',
}
const hoverStyles = {
backgroundColor: '#eaeaea',
}
Object.assign(newP.style, styles);
newP.innerText = formattedCommand;
newP.classList.add('repozenCommand');
newP.addEventListener('mouseover', () => {
Object.assign(newP.style, hoverStyles);
});
newP.addEventListener('mouseout', () => {
Object.assign(newP.style, styles);
});
newP.addEventListener('click', () => {
copyToClipboard(formattedCommand, newP);
});
return newP;
}
const cardIdButton = () => {
const cardId = document.title.substring(document.title.lastIndexOf('#'));
const newButton = document.createElement('button');
const styles = {
width: '20%',
background: '#ccc',
fontSize: '16px',
color: 'black',
border: 'none',
transition: 'background-color 0.3s',
borderRadius: '0 4px 4px 0',
}
const hoverStyles = {
background: '#eaeaea',
color: '#555',
}
Object.assign(newButton.style, styles);
newButton.innerText = 'Copy ID';
newButton.classList.add('addButton');
newButton.addEventListener('mouseover', () => {
Object.assign(newButton.style, hoverStyles);
newButton.innerText = cardId;
});
newButton.addEventListener('mouseout', () => {
Object.assign(newButton.style, styles);
newButton.innerText = 'Copy ID';
});
newButton.addEventListener('click', () => {
copyToClipboard(cardId, newButton, false);
});
return newButton;
}
const adaptTaskNameBlock = () => {
const taskNameBlock = document.querySelector(".task-name-block");
Object.assign(taskNameBlock.style, { top: '48px' });
}
const formattedCommand = (taskName) => {
const tagsElement = (taskInfo.querySelector('.cu-tags-select__name') !== null) ? taskInfo.querySelector('.cu-tags-select__name').innerText + "/" : "";
const formattedString = tagsElement + taskName.split(" ").join("_");
return `git checkout -b "${formattedString}"`;
}
const copyToClipboard = (text, element, notified = true) => {
const temp = document.createElement('textarea');
temp.value = text;
document.body.appendChild(temp);
temp.select();
document.execCommand('copy');
document.body.removeChild(temp);
if (notified) { copiedNotification(text, element) }
}
const copiedNotification = (originalText, element) => {
const tempText = 'Copied !';
element.innerText = tempText;
setTimeout(() => {
element.innerText = originalText;
}, 1000);
}
const mutations = () => {
const handleMutations = mutationsList => {
for (let mutation of mutationsList) {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
if (body) {
handleCardClick();
}
}
}
};
const observer = new MutationObserver(handleMutations);
const body = document.body;
const observerConfig = { attributes: true };
observer.observe(body, observerConfig);
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment