---
# System prepended metadata

title: Trello analytics

---

# Trello analytics

- Insert code to chrome dev tools while open trello
- wait for console.log "Done"
- use vars to get statistics
 

```javascript=
const board = await fetch(
  "https://trello.com/b/gVZUCX4f/devextremegrids.json"
).then((r) => r.json());

const getDoneSprints = (board) => {
  const regex = /^Done in Sprint (\d+)/;
  const getSprintNumber = (card) => {
    const number = regex.exec(card.name)[1];
    return number;
  };
  return board.lists
    .filter((l) => regex.exec(l.name))
    .map((l) => ({
      ...l,
      number: getSprintNumber(l),
    }))
    .sort((a, b) => b.number - a.number);
};

const getCardsInList = (allCards, list) => {
  return allCards.filter((c) => c.idList === list.id);
};

const lists = {
  dones: getDoneSprints(board),
  complex: board.lists.find((l) => l.name === "Complex Bugs"),
  incoming: board.lists.find((l) => l.name === "Incoming Bugs"),
  bugs: board.lists.find((l) => l.name === "Bugs"),
  doing: board.lists.find((l) => l.name === "Doing [7]"),
  waiting: board.lists.find((l) => l.name === "Waiting [6]"),
  review: board.lists.find((l) => l.name === "Review [6]"),
  testing: board.lists.find((l) => l.name === "Testing [6]"),
};

for (const listName in lists) {
  if (listName === "dones") {
    lists[listName].cards = board.cards.filter((card) =>
      lists.dones.map((l) => l.id).includes(card.idList)
    );
  } else {
    lists[listName].cards = board.cards.filter(
      (card) => card.idList === lists[listName].id && !card.closed 
    );
  }
}

const groupByFeatures = (cards) => {
  const _byCategories = {};
  cards.forEach((c) => {
    c.labels.forEach((l) => {
      if (l.name.includes("feature")) {
        _byCategories[l.name] = _byCategories[l.name] || [];
        _byCategories[l.name].push(c);
      }
    });
  });

  const byCategories = Object.keys(_byCategories)
    .map((k) => ({
      name: k,
      cards: _byCategories[k],
      length: _byCategories[k].length,
    }))
    .sort((a, b) => b.length - a.length);

  byCategories.forEach((cat) => {
    const isAlpha = function (ch) {
      return (
        typeof ch === "string" &&
        ch.length === 1 &&
        ((ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z"))
      );
    };

    const name = Array.from(cat.name.replace("feature:", ""))
      .filter(isAlpha)
      .join("");
    byCategories[name] = cat;
  });

  return byCategories;
};

const isActive = (card) => {
  return !doneLists.map((l) => l.id).includes(card.idList);
};

const hasLabel = (label) => (card) => {
  return card.labels.some((l) => l.name === label);
};

const hasNotLabel = (label) => (card) => {
  return card.labels.every((l) => l.name !== label);
};

const isBug = hasLabel("Bug");

console.log("Done");
```