Skip to content

Instantly share code, notes, and snippets.

@ajubin
Last active March 16, 2021 17:32
Show Gist options
  • Save ajubin/5260a08902234cc9c83d4c8dd4007fde to your computer and use it in GitHub Desktop.
Save ajubin/5260a08902234cc9c83d4c8dd4007fde to your computer and use it in GitHub Desktop.
Trello - Useful bookmarklet to know how much was done in storypoints

Trello - Utils

Sum storypoints of attributed cards in a column and group them by last activity date.

For multi members cards, only your representation is shown.

How to

Setup

To use them simply create a new bookmark and copy past the code in the url field.

Execution

Go on the json representation of your Trello by stripping the slug and add a .json.

For instance, replace board following board url https://trello.com/b/i6VocExI/ekwateur by https://trello.com/b/i6VocExI.json

Then you only need to click on the bookmark to execute the script.

Code

javascript: !function() {
  function groupBy(objectArray, property) {
  return objectArray.reduce((acc, obj) => {
    const key = obj[property];
    if (!acc[key]) {
      acc[key] = [];
    }
    acc[key].push(obj);
    return acc;
  }, {});
}

function getStoryPoints(card) {
  try {
    return parseFloat(/\(([^)]+)\)/.exec(card.name)[1]);
  } catch (error) {
    console.error('Cannot retrieve storypoints of ', card.name);
    return 0;
  }
}

function getSummaryInDone(doneColumn, username) {
  const data = JSON.parse(document.getElementsByTagName('pre')[0].innerText);
  if (!data) {
    throw new Error('No content found, do you see JSON in your tab ?');
  }
  const doneListId = data.lists.find(item => item.name.includes(doneColumn))?.id;
  if (!doneListId) {
    throw new Error('No done list found, did you enter the right name ?');
  }
  const userId = data.members.find(member => member.username === username)?.id;
  if (!userId) {
    throw new Error(`No user found, do you see yourself on https://trello.com/${username}`);
  }

  const doneCard = data.cards
    .filter(card => card.idList === doneListId)
    .filter(card => card.idMembers.includes(userId));

  console.log(JSON.stringify(doneListId, null, 2));
  const myDoneCardsWithExtraInfo = doneCard.map(card => ({
    ...card,
    storypoints: getStoryPoints(card) / card.idMembers.length,
    day: card.dateLastActivity.split('T')[0],
  }));
  const summary = groupBy(myDoneCardsWithExtraInfo, 'day');
  const result = Object.keys(summary)
    .map(date => ({
      date,
      total: summary[date].reduce((sum, card) => sum + card.storypoints, 0),
      ticketName: summary[date].map(card => card.name),
    }))
    .sort((a, b) => a.date < b.date ?-1:1);
  return result;
}

try {
  const doneColumn = prompt('Copier le nom de la colonne a analyser', 'Done Sprint 58 🎉');
  const username = prompt('entrez ici votre username', 'antoinejubin1');
  const result = getSummaryInDone(doneColumn, username);
  console.log(doneColumn, username, JSON.stringify(result, null, 2));
  alert(`Done on col ${doneColumn} by ${username} \n ${JSON.stringify(result, null, 2)} `);
} catch (error) {
  console.error('Error:', error);
  console.log('Please check that all cards you are tagged on have storypoints');
}
}();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment