trello-sprinter
Version:
Provides summarizations of sprint activity in a Trello project
1,443 lines (1,174 loc) • 167 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["TrelloSprinter"] = factory();
else
root["TrelloSprinter"] = factory();
})(self, () => {
return /******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./index.js":
/*!******************!*\
!*** ./index.js ***!
\******************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "TrelloSprinter": () => (/* reexport safe */ _src_TrelloSprinter__WEBPACK_IMPORTED_MODULE_1__.TrelloSprinter),
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _trello_scss__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./trello.scss */ "./trello.scss");
/* harmony import */ var _src_TrelloSprinter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./src/TrelloSprinter */ "./src/TrelloSprinter.js");
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_src_TrelloSprinter__WEBPACK_IMPORTED_MODULE_1__.TrelloSprinter);
/***/ }),
/***/ "./src/Board.js":
/*!**********************!*\
!*** ./src/Board.js ***!
\**********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Board": () => (/* binding */ Board)
/* harmony export */ });
/* harmony import */ var _Member__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Member */ "./src/Member.js");
/* harmony import */ var _List__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./List */ "./src/List.js");
/* harmony import */ var _Card__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Card */ "./src/Card.js");
/* harmony import */ var _Update__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Update */ "./src/Update.js");
/* harmony import */ var _Comment__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Comment */ "./src/Comment.js");
/*
* Representation of a Trello Board
*/
var Board = function Board(data, options) {
this.data = data;
this.id = data.id;
this.name = data.name;
this.lists = [];
this.members = {};
this.options = options;
this.find_card = function (id) {
for (var i = 0; i < this.lists.length; i++) {
var card = this.lists[i].find_card(id);
if (card !== null) {
return card;
}
}
return null;
};
this.add_member = function (member) {
this.members[member.id] = member;
};
};
Board.fetch = function (trello, name, options, msg, success, failure) {
msg.innerText = 'Fetching board ' + name; /// Keeps track of how many open async calls there are right now
var active = 0; // Will be set to point to a new Board object
var board = null;
async_start();
trello.get("/member/me/boards?fields=all", function (data) {
for (var i = 0; i < data.length; i++) {
var boardData = data[i];
if (boardData.name.toLowerCase() === name.toLowerCase()) {
// We have found the board (if not closed)
if (!boardData.closed) {
// Create the board object
board = new Board(boardData, options); // Fetch the membership
fetch_membership(board); // Fetch the lists for the board
fetch_lists(board);
break;
}
}
}
if (board === null) {
failure("Unable to find Trello board " + name);
return;
}
async_end();
}, function (data) {
failure("Unable to fetch Trello boards");
}, msg);
/**
* Fetch the membership of the board.
* @param board Board to fetch for
*/
function fetch_membership(board) {
async_start();
trello.get("/board/" + board.id + "/members?fields=all", function (data) {
data.forEach(function (memberData) {
var member = new _Member__WEBPACK_IMPORTED_MODULE_0__.Member(board, memberData);
board.add_member(member);
});
async_end();
}, function (data) {
failure("Unable to fetch Trello membership");
}, msg);
}
function fetch_lists(board) {
msg.innerText = "Fetching lists for " + name;
async_start();
trello.get("/boards/" + board.id + "/lists?filter=open", function (data) {
data.forEach(function (listData) {
if (!listData.closed) {
var list = new _List__WEBPACK_IMPORTED_MODULE_1__.List(board, listData);
board.lists.push(list);
}
});
fetch_cards(board);
async_end();
}, function (data) {
failure("Unable to fetch Trello lists");
}, msg);
}
/**
* Fetch all cards as a single batch operation.
* @param board Board we are fetching for
*/
function fetch_cards(board) {
msg.innerText = "Fetching cards"; // Collect up all URLs for all of the lists
var urls = '';
for (var i = 0; i < board.lists.length; i++) {
var list = board.lists[i];
if (urls.length > 0) {
urls += ',';
}
urls += "/lists/" + list.id + "/cards/open";
} // Get get it
async_start();
trello.get("/batch?urls=" + urls, function (data) {
var _loop = function _loop(_i) {
var list = board.lists[_i];
var cardsData = data[_i][200];
cardsData.forEach(function (cardData) {
if (!cardData.closed) {
var card = new _Card__WEBPACK_IMPORTED_MODULE_2__.Card(board, list, cardData);
if (options.after !== null) {
if (card.created.getTime() / 1000 > options.after) {
list.add_card(card);
}
} else {
list.add_card(card);
}
}
});
};
// Loop over the result for each provided URL
for (var _i = 0; _i < data.length && _i < board.lists.length; _i++) {
_loop(_i);
}
fetch_actions(board);
async_end();
}, function (data) {
failure("Unable to fetch Trello cards");
}, msg);
}
function fetch_actions(board) {
async_start();
trello.get("/board/" + board.id + "/actions?filter=commentCard,updateCard:idList&limit=1000", function (data) {
data.forEach(function (action) {
if (!action.closed) {
if (action.type === "commentCard") {
var card = board.find_card(action.data.card.id);
if (card !== null) {
var comment = new _Comment__WEBPACK_IMPORTED_MODULE_4__.Comment(board, card, action);
card.comments.push(comment);
} //console.log(action);
} else if (action.type === 'updateCard') {
var _card = board.find_card(action.data.card.id);
if (_card !== null) {
var update = new _Update__WEBPACK_IMPORTED_MODULE_3__.Update(board, _card, action);
_card.updates.push(update);
} //console.log(action);
}
}
});
board.lists.forEach(function (list) {
list.cards.forEach(function (card) {
card.sort_updates();
});
});
async_end();
}, function (data) {
failure("Unable to fetch Trello card information");
}, msg);
}
function async_start() {
active++;
}
function async_end() {
active--;
if (active === 0) {
success(board);
}
}
};
Board.prototype.find_list = function (name) {
name = name.toLowerCase();
for (var i = 0; i < this.lists.length; i++) {
var list = this.lists[i];
if (list.name.toLowerCase() === name) {
return list;
}
}
return null;
};
/***/ }),
/***/ "./src/BoardView.js":
/*!**************************!*\
!*** ./src/BoardView.js ***!
\**************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "BoardView": () => (/* binding */ BoardView)
/* harmony export */ });
/* harmony import */ var _DataView__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./DataView */ "./src/DataView.js");
/* harmony import */ var _Util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Util */ "./src/Util.js");
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
/**
* @file
* Standard Trello board view
*/
var BoardView = function BoardView(div, board) {
_DataView__WEBPACK_IMPORTED_MODULE_0__.DataView.call(this);
this.present = function () {
var view = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.createElement('div', 'trello-view');
div.appendChild(view);
var _iterator = _createForOfIteratorHelper(board.lists),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var list = _step.value;
presentList(view, list);
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
};
var presentList = function presentList(view, list) {
var header = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.createElement('h3', 'trello-plus');
header.innerText = list.name;
view.appendChild(header);
var expander = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.createElement('div', 'trello-expand');
expander.style.display = 'none';
view.appendChild(expander);
header.addEventListener('click', function (event) {
if (expander.style.display === 'none') {
expander.style.display = 'block';
_Util__WEBPACK_IMPORTED_MODULE_1__.Util.removeClass(header, 'trello-plus');
_Util__WEBPACK_IMPORTED_MODULE_1__.Util.addClass(header, 'trello-minus');
} else {
expander.style.display = 'none';
_Util__WEBPACK_IMPORTED_MODULE_1__.Util.removeClass(header, 'trello-minus');
_Util__WEBPACK_IMPORTED_MODULE_1__.Util.addClass(header, 'trello-plus');
}
});
var count = list.count_members();
var members = '<em>Cards:</em>[' + list.cards.length + '] ';
for (var c in count) {
if (count.hasOwnProperty(c)) {
members += count[c].member.name + ':[' + count[c].cnt + '] ';
}
}
var countEl = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.createElement('p', 'trello-count');
expander.appendChild(countEl);
countEl.innerHTML = members;
var _iterator2 = _createForOfIteratorHelper(list.cards),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var card = _step2.value;
presentCard(expander, card);
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
};
var presentCard = function presentCard(div, card) {
//
// Heading
//
var date = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.formatDatetime(card.created);
var cardDiv = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.createElement('div', 'trello-card');
div.appendChild(cardDiv);
cardDiv.innerHTML = "<h4><span class=\"trello-date\">".concat(date, "</span>").concat(card.name, "</h4>"); //
// Members
//
var members = '';
var _iterator3 = _createForOfIteratorHelper(card.members),
_step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
var id = _step3.value;
var member = card.board.members[id];
if (members.length > 0) {
members += ' / ';
}
members += '<span>' + member.name + '</span>';
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
var membersP = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.createElement('p', 'trello-card-members');
cardDiv.appendChild(membersP);
membersP.innerHTML = members; //
// Description
//
var desc = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.createElement('div', 'trello-description');
cardDiv.appendChild(desc);
desc.innerHTML = card.desc;
presentComments(cardDiv, card);
presentUpdates(cardDiv, card);
};
this.presentCard = presentCard;
var presentComments = function presentComments(div, card) {
if (card.comments.length === 0) {
return;
}
var commentDiv = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.createElement('div', 'trello-comments');
div.appendChild(commentDiv);
var _iterator4 = _createForOfIteratorHelper(card.comments),
_step4;
try {
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
var comment = _step4.value;
var member = card.board.members[comment.member];
var memberName = member !== undefined ? member.name : "undefined";
var date = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.formatDatetime(comment.date);
var h5 = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.createElement('h5');
commentDiv.appendChild(h5);
h5.innerHTML = "<span class=\"trello-date\">".concat(date, "</span>").concat(memberName);
var textDiv = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.createElement('div');
commentDiv.appendChild(textDiv);
textDiv.innerHTML = comment.text;
}
} catch (err) {
_iterator4.e(err);
} finally {
_iterator4.f();
}
};
var presentUpdates = function presentUpdates(div, card) {
if (card.updates.length === 0) {
return;
}
var updateDiv = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.createElement('div', 'trello-updates');
div.appendChild(updateDiv);
var _iterator5 = _createForOfIteratorHelper(card.updates),
_step5;
try {
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
var update = _step5.value;
var member = card.board.members[update.member];
var memberName = member !== undefined ? member.name : "undefined";
var date = _Util__WEBPACK_IMPORTED_MODULE_1__.Util.formatDatetime(update.date);
var p = document.createElement('p');
updateDiv.appendChild(p);
p.innerHTML = '<span class="date">' + date + '</span> ' + memberName + ' moved from <span class="list">' + update.listBefore + '</span> to <span class="list">' + update.listAfter + '</span>';
}
} catch (err) {
_iterator5.e(err);
} finally {
_iterator5.f();
}
};
}; /// @cond
BoardView.prototype = Object.create(_DataView__WEBPACK_IMPORTED_MODULE_0__.DataView.prototype);
BoardView.prototype.constructor = BoardView; /// @endcond
/***/ }),
/***/ "./src/Card.js":
/*!*********************!*\
!*** ./src/Card.js ***!
\*********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Card": () => (/* binding */ Card)
/* harmony export */ });
/* harmony import */ var _Util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Util */ "./src/Util.js");
/**
* @file
* Representation of a Trello list in a board
*/
var Card = function Card(board, list, data) {
var that = this;
this.board = board;
this.list = list;
this.id = data.id;
this.name = _Util__WEBPACK_IMPORTED_MODULE_0__.Util.strip_tags(data.name);
this.data = data;
this.desc = '<p>' + _Util__WEBPACK_IMPORTED_MODULE_0__.Util.strip_tags(data.desc).replace(/\n/gm, '<p>') + '</p>';
this.created = new Date(parseInt(data.id.substr(0, 8), 16) * 1000);
this.members = [];
data.idMembers.forEach(function (id) {
that.members.push(id);
});
this.comments = [];
this.updates = [];
};
Card.prototype.sort_updates = function () {
this.updates.sort(function (a, b) {
if (a.date < b.date) {
return -1;
} else if (a.date == b.date) {
return 0;
} else {
return 1;
}
});
};
/**
* Determine the last time this card was moved.
* This is used to determine when a completed card was
* moved to Completed.
*/
Card.prototype.final_time = function () {
if (this.updates.length > 0) {
return this.updates[this.updates.length - 1].date;
}
return this.created;
};
/**
* Count members from a collection of cards.
* @param board Board object
* @param list array of Card objects
* @returns object with id as property to object {cnt: ?, member: ?}
*/
Card.count_members = function (board, list) {
var count = {};
list.forEach(function (card) {
card.members.forEach(function (id) {
var member = board.members[id];
if (count.hasOwnProperty(member.id)) {
count[member.id].cnt++;
} else {
count[member.id] = {
cnt: 1,
member: member
};
}
});
});
return count;
};
/***/ }),
/***/ "./src/Comment.js":
/*!************************!*\
!*** ./src/Comment.js ***!
\************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Comment": () => (/* binding */ Comment)
/* harmony export */ });
/* harmony import */ var _Util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Util */ "./src/Util.js");
/**
* @file
* Representation of a Trello comment on a card
*/
/**
Array
(
[id] => 57eec1ca22684646b1193abd
[idMemberCreator] => 57ec1bdafeedcbbc73d600d1
[data] => Array
(
[list] => Array
(
[name] => Design
[id] => 57e920a2b34518203fd5f319
)
[board] => Array
(
[shortLink] => i9eXE4yJ
[name] => Project 1 Team: Arbo
[id] => 57e9204ac3f323f1785d7be4
)
[card] => Array
(
[shortLink] => Fggvd4nX
[idShort] => 21
[name] => Visual Paradigm Class Design
[id] => 57eec0776fd005f7b81c8239
)
[text] => Visual Paradigm Class Design
)
[type] => commentCard
[date] => 2016-09-30T19:49:30.974Z
[memberCreator] => Array
(
[id] => 57ec1bdafeedcbbc73d600d1
[avatarHash] =>
[fullName] => Brittany Galliers
[initials] => BG
[username] => brittanygalliers1
)
* @param board
* @param card
* @param data
* @constructor
*/
var Comment = function Comment(board, card, data) {
this.board = board;
this.card = card;
this.member = data.idMemberCreator;
this.text = '<p>' + _Util__WEBPACK_IMPORTED_MODULE_0__.Util.strip_tags(data.data.text).replace(/\n/gm, '<p>') + '</p>';
this.data = data;
this.date = new Date(Date.parse(data.date));
};
/***/ }),
/***/ "./src/DataView.js":
/*!*************************!*\
!*** ./src/DataView.js ***!
\*************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "DataView": () => (/* binding */ DataView)
/* harmony export */ });
/*
* Base object for views of Trello data.
*/
var DataView = function DataView() {};
DataView.prototype.present = function (div, board) {};
/***/ }),
/***/ "./src/DisconnectedView.js":
/*!*********************************!*\
!*** ./src/DisconnectedView.js ***!
\*********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "DisconnectedView": () => (/* binding */ DisconnectedView)
/* harmony export */ });
/* harmony import */ var _Util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Util */ "./src/Util.js");
var DisconnectedView = function DisconnectedView(element, trello, options) {
// Ensure empty
element.innerHTML = '';
var div = document.createElement('div');
element.appendChild(div);
_Util__WEBPACK_IMPORTED_MODULE_0__.Util.addClass(div, 'trello-sprinter');
var p = document.createElement('p');
div.appendChild(p);
_Util__WEBPACK_IMPORTED_MODULE_0__.Util.addClass(p, 'center');
var button = document.createElement('button');
p.appendChild(button);
button.innerText = 'Connect to Trello';
button.addEventListener('click', function (event) {
event.preventDefault();
trello.authorize();
});
};
/***/ }),
/***/ "./src/List.js":
/*!*********************!*\
!*** ./src/List.js ***!
\*********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "List": () => (/* binding */ List)
/* harmony export */ });
/* harmony import */ var _Card__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Card */ "./src/Card.js");
/**
* @file
* Representation of a Trello list in a board
*/
var List = function List(board, data) {
this.board = board;
this.id = data.id;
this.name = data.name;
this.data = data;
this.cards = [];
this.cards_by_id = {};
};
List.prototype.add_card = function (card) {
this.cards.push(card);
this.cards_by_id[card.id] = card;
};
List.prototype.find_card = function (id) {
if (this.cards_by_id.hasOwnProperty(id)) {
return this.cards_by_id[id];
}
return null;
};
List.prototype.count_members = function () {
return _Card__WEBPACK_IMPORTED_MODULE_0__.Card.count_members(this.board, this.cards);
};
/***/ }),
/***/ "./src/MainView.js":
/*!*************************!*\
!*** ./src/MainView.js ***!
\*************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "MainView": () => (/* binding */ MainView)
/* harmony export */ });
/* harmony import */ var _Util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Util */ "./src/Util.js");
/* harmony import */ var _Board__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Board */ "./src/Board.js");
/* harmony import */ var _BoardView__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BoardView */ "./src/BoardView.js");
/* harmony import */ var _Sprints_SprintView__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Sprints/SprintView */ "./src/Sprints/SprintView.js");
/* harmony import */ var _Sprints_SprintTableView__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Sprints/SprintTableView */ "./src/Sprints/SprintTableView.js");
/* harmony import */ var _DisconnectedView__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./DisconnectedView */ "./src/DisconnectedView.js");
var MainView = function MainView(element, trello, options) {
// Ensure empty
element.innerHTML = '';
var div = document.createElement('div');
element.appendChild(div);
_Util__WEBPACK_IMPORTED_MODULE_0__.Util.addClass(div, 'trello-sprinter');
var p = document.createElement('p');
div.appendChild(p);
_Util__WEBPACK_IMPORTED_MODULE_0__.Util.addClass(p, 'center');
var button = document.createElement('button');
p.appendChild(button);
button.innerText = 'Disconnect';
button.addEventListener('click', function (event) {
event.preventDefault();
trello.disconnect();
new _DisconnectedView__WEBPACK_IMPORTED_MODULE_5__.DisconnectedView(element, trello, options);
});
var pStatus = _Util__WEBPACK_IMPORTED_MODULE_0__.Util.createElement('p', 'trello-status');
pStatus.innerText = 'Connecting to Trello...';
div.appendChild(pStatus);
var pMsg = _Util__WEBPACK_IMPORTED_MODULE_0__.Util.createElement('p', 'trello-msg');
div.appendChild(pMsg);
_Board__WEBPACK_IMPORTED_MODULE_1__.Board.fetch(trello, options.board, options, pMsg, function (board) {
// Success
pStatus.innerText = 'Trello Board: ' + board.name;
pMsg.parentNode.removeChild(pMsg);
for (var view in options.views) {
switch (view) {
case 'board':
var boardView = new _BoardView__WEBPACK_IMPORTED_MODULE_2__.BoardView(div, board);
boardView.present();
break;
case 'sprint':
var sprintView = new _Sprints_SprintView__WEBPACK_IMPORTED_MODULE_3__.SprintView(div, board, options.views.sprint);
sprintView.present();
break;
case 'sprintTable':
var sprintTableView = new _Sprints_SprintTableView__WEBPACK_IMPORTED_MODULE_4__.SprintTableView(div, board, options.views.sprintTable);
sprintTableView.present();
break;
}
}
}, function (msg) {
// Failure
pMsg.parentNode.removeChild(pMsg);
pStatus.innerText = msg;
}); //trello.fetch();
};
/***/ }),
/***/ "./src/Member.js":
/*!***********************!*\
!*** ./src/Member.js ***!
\***********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Member": () => (/* binding */ Member)
/* harmony export */ });
/*
* Representation of a Trello member in a board
*/
var Member = function Member(board, data) {
this.board = board;
this.id = data.id;
this.name = data.fullName;
this.data = data;
};
/***/ }),
/***/ "./src/Sprints/Sprint.js":
/*!*******************************!*\
!*** ./src/Sprints/Sprint.js ***!
\*******************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Sprint": () => (/* binding */ Sprint)
/* harmony export */ });
/*
* Represents a single sprint in the sprints analysis
*/
var Sprint = function Sprint(sprints, start, end) {
this.sprints = sprints;
this.start_meeting = start;
this.end_meeting = end;
this.completed = [];
};
Sprint.prototype.end_time = function () {
return new Date(this.end_meeting.created.getTime() + this.sprints.sprint_time_slop * 1000);
};
/***/ }),
/***/ "./src/Sprints/SprintMember.js":
/*!*************************************!*\
!*** ./src/Sprints/SprintMember.js ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "SprintMember": () => (/* binding */ SprintMember)
/* harmony export */ });
/**
* @file
* Team member statistics for a sprint
*/
var SprintMember = function SprintMember(sprints, member) {
this.member = member;
this.sprints = sprints;
this.meetings_count = 0;
this.meetings_attended = 0;
this.completed_count = 0;
this.completed_total = 0;
this.reviews_count = 0;
this.reviews_total = 0;
};
SprintMember.prototype.meetings_percentage = function () {
if (this.meetings_count <= this.sprints.meetings_slop) {
return '(insufficient meetings)';
}
var per = this.meetings_attended / (this.meetings_count - this.sprints.meetings_slop);
if (per > 1) {
per = 1;
}
return per.toFixed(2);
};
SprintMember.prototype.completed_factor = function (teamSize) {
if (this.completed_total === 0) {
return 0;
}
var factor = this.completed_count / (this.completed_total / teamSize * this.sprints.completed_factor);
if (factor > 1) {
factor = 1;
}
return factor.toFixed(2);
};
SprintMember.prototype.reviewing_factor = function (teamSize) {
if (this.reviews_total === 0) {
return 0;
}
var factor = this.reviews_count / (this.reviews_total / teamSize * this.sprints.reviewing_factor);
if (factor > 1) {
factor = 1;
}
return factor.toFixed(2);
};
/***/ }),
/***/ "./src/Sprints/SprintTableView.js":
/*!****************************************!*\
!*** ./src/Sprints/SprintTableView.js ***!
\****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "SprintTableView": () => (/* binding */ SprintTableView)
/* harmony export */ });
/* harmony import */ var _DataView__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../DataView */ "./src/DataView.js");
/* harmony import */ var _Sprints__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Sprints */ "./src/Sprints/Sprints.js");
/* harmony import */ var _Util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Util */ "./src/Util.js");
/* harmony import */ var _Card__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Card */ "./src/Card.js");
/* harmony import */ var _BoardView__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../BoardView */ "./src/BoardView.js");
/*
* Trello board view that displays sprint result in a table.
*/
var SprintTableView = function SprintTableView(div, board, options) {
_DataView__WEBPACK_IMPORTED_MODULE_0__.DataView.call(this);
var addHeadings = true;
if (options.addHeadings !== undefined) {
addHeadings = options.addHeadings;
}
this.present = function () {
var view = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('div', 'trello-sprint-table');
div.appendChild(view);
var table = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('table');
view.appendChild(table);
if (options["class"] !== undefined) {
_Util__WEBPACK_IMPORTED_MODULE_2__.Util.addClass(table, options["class"]);
} //
// Create the sprint analysis
//
var sprints = new _Sprints__WEBPACK_IMPORTED_MODULE_1__.Sprints(board);
var teamSize = sprints.num_members();
if (addHeadings) {
tableHeading(table, board, sprints);
}
var rowHTML = '';
function item(data) {
rowHTML += '<td>' + data + '</td>';
}
for (var id in sprints.members) {
if (sprints.members.hasOwnProperty(id)) {
var member = sprints.members[id];
var id = member.member.id;
rowHTML = ''; // Our statistics
item(board.name);
item(teamSize);
item(member.member.name);
item(member.meetings_attended);
item(member.meetings_count);
item(member.meetings_percentage());
item(member.completed_count);
item(member.completed_total);
item(member.completed_factor(teamSize));
item(member.reviews_count);
item(member.reviews_total);
item(member.reviewing_factor(teamSize));
item(sprints.sprints.length);
sprints.sprints.forEach(function (sprint) {
var cnt = 0;
sprint.completed.forEach(function (card) {
if (card.members.length == 1 && card.members[0] == id) {
cnt++;
}
});
item(cnt);
item(sprint.completed.length);
});
if (!isNaN(addHeadings)) {
for (var i = sprints.sprints.length; i < addHeadings; i++) {
item(" ");
item(" ");
}
}
var tr = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('tr');
tr.innerHTML = rowHTML;
table.appendChild(tr);
}
}
};
var tableHeading = function tableHeading(table, board, sprints) {
var tr = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('tr');
table.appendChild(tr);
if (options.tr1class !== undefined) {
_Util__WEBPACK_IMPORTED_MODULE_2__.Util.addClass(tr, options.tr1class);
}
var rowHTML = '';
function item(data) {
rowHTML += '<th><div>' + data + '</div></th>';
}
item("Team");
item("#");
item("Member");
item("Attended");
item("Total");
item("%");
item("Completed");
item("Total");
item("%");
item("Reviews");
item("Total");
item("%");
item("Sprints");
if (addHeadings === true) {
for (var i = 1; i <= sprints.sprints.length; i++) {
item(i);
item("#");
}
} else {
for (var i = 1; i <= addHeadings; i++) {
item(i);
item("#");
}
}
tr.innerHTML = rowHTML;
};
}; /// @cond
SprintTableView.prototype = Object.create(_DataView__WEBPACK_IMPORTED_MODULE_0__.DataView.prototype);
SprintTableView.prototype.constructor = SprintTableView; /// @endcond
SprintTableView.prototype.table_headings = function (board, sprints) {};
/***/ }),
/***/ "./src/Sprints/SprintView.js":
/*!***********************************!*\
!*** ./src/Sprints/SprintView.js ***!
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "SprintView": () => (/* binding */ SprintView)
/* harmony export */ });
/* harmony import */ var _DataView__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../DataView */ "./src/DataView.js");
/* harmony import */ var _Sprints__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Sprints */ "./src/Sprints/Sprints.js");
/* harmony import */ var _Util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Util */ "./src/Util.js");
/* harmony import */ var _Card__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Card */ "./src/Card.js");
/* harmony import */ var _BoardView__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../BoardView */ "./src/BoardView.js");
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
/**
* @file
* Trello board view that displays sprint results
*/
var SprintView = function SprintView(div, board) {
_DataView__WEBPACK_IMPORTED_MODULE_0__.DataView.call(this); // This uses BoardView to draw what it knows how to draw
var board_view = new _BoardView__WEBPACK_IMPORTED_MODULE_4__.BoardView(div, board);
this.present = function () {
//
// Create the sprint analysis
//
var sprints = new _Sprints__WEBPACK_IMPORTED_MODULE_1__.Sprints(board);
var view = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('div', 'trello-sprints');
div.appendChild(view);
var h2 = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('h2');
h2.innerText = 'Sprints Analysis';
view.appendChild(h2);
present_errors(view, sprints);
present_warnings(view, sprints);
if (sprints.errors.length > 0) {
return;
}
present_sprints(view, sprints);
present_members(view, sprints);
};
var present_errors = function present_errors(div, sprints) {
if (sprints.errors.length === 0) {
return;
}
var errors = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('div', 'trello-errors');
div.appendChild(errors);
errors.innerHTML = '<h3>Errors</h3>';
var _iterator = _createForOfIteratorHelper(sprints.errors),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var error = _step.value;
var p = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('p');
errors.appendChild(p);
p.innerHTML = '<span class="trello-code">' + error.code + ':</span> ' + error.msg;
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
};
var present_warnings = function present_warnings(div, sprints) {
if (sprints.warnings.length === 0) {
return;
}
var warnings = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('div', 'trello-warnings');
div.appendChild(warnings);
warnings.innerHTML = '<h3>Warnings</h3>';
var _iterator2 = _createForOfIteratorHelper(sprints.warnings),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var warning = _step2.value;
var p = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('p');
warnings.appendChild(p);
p.innerHTML = '<span class="trello-code">' + warning.code + ':</span> ' + warning.msg;
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
};
var present_sprints = function present_sprints(div, sprints) {
var view = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('div', 'trello-view');
div.appendChild(view);
for (var s = 1; s <= sprints.sprints.length; s++) {
var sprint = sprints.sprints[s - 1];
present_sprint(view, sprints, s, sprint);
}
};
var present_sprint = function present_sprint(div, sprints, num, sprint) {
var fmDate = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.formatDatetime(sprint.start_meeting.created);
var toDate = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.formatDatetime(sprint.end_meeting.created);
var completed = sprint.completed.length; //
// Member counts for completed
//
var counts = _Card__WEBPACK_IMPORTED_MODULE_3__.Card.count_members(sprints.board, sprint.completed);
var totalCompleted = 0;
var _iterator3 = _createForOfIteratorHelper(sprints.sprints),
_step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
var _sprint = _step3.value;
totalCompleted += _sprint.completed.length;
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
var completionFactor = 0.00;
if (totalCompleted > 0) {
completionFactor = completed / (totalCompleted / sprints.sprints.length * 0.8);
if (completionFactor > 1) {
completionFactor = 1;
}
}
completionFactor = completionFactor.toFixed(2);
var header = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('h3', 'trello-plus');
div.appendChild(header);
header.innerHTML = '<span class="date">' + completed + ' tasks ' + completionFactor + ' / ' + fmDate + ' to ' + toDate + '</span>Sprint: ' + num;
var expander = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('div', 'trello-expand');
expander.style.display = 'none';
div.appendChild(expander);
header.addEventListener('click', function (event) {
if (expander.style.display === 'none') {
expander.style.display = 'block';
_Util__WEBPACK_IMPORTED_MODULE_2__.Util.removeClass(header, 'trello-plus');
_Util__WEBPACK_IMPORTED_MODULE_2__.Util.addClass(header, 'trello-minus');
} else {
expander.style.display = 'none';
_Util__WEBPACK_IMPORTED_MODULE_2__.Util.removeClass(header, 'trello-minus');
_Util__WEBPACK_IMPORTED_MODULE_2__.Util.addClass(header, 'trello-plus');
}
});
board_view.presentCard(expander, sprint.start_meeting);
board_view.presentCard(expander, sprint.end_meeting); //
// Completed
//
var pCompleted = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('p', 'trello-completed-header');
expander.appendChild(pCompleted);
pCompleted.innerText = 'Sprint Completed Tasks';
var pMembers = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('p', 'trello-count');
expander.appendChild(pMembers);
var members = '<em>Completed:</em>[' + sprint.completed.length + '] ';
for (var c in counts) {
if (counts.hasOwnProperty(c)) {
members += counts[c].member.name + ':[' + counts[c].cnt + '] ';
}
}
pMembers.innerHTML = members; //
// Present completed cards
//
for (var i = 0; i < sprint.completed.length; i++) {
var _completed = sprint.completed[i];
board_view.presentCard(expander, _completed);
}
};
var present_members = function present_members(div, sprints) {
var membersDiv = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('div', 'trello-members');
div.appendChild(membersDiv);
for (var id in sprints.members) {
if (sprints.members.hasOwnProperty(id)) {
var member = sprints.members[id];
present_member(membersDiv, sprints, member);
}
}
present_info(membersDiv, sprints);
};
var present_member = function present_member(div, sprints, member) {
var memberDiv = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('div', 'trello-member');
div.appendChild(memberDiv);
var meetings = sprints.meetings_slop === 1 ? ' meeting' : ' meetings';
var teamSize = sprints.num_members();
memberDiv.innerHTML = '<h4>' + member.member.name + '</h4>' + '<p>Meetings attended: ' + member.meetings_attended + '/' + member.meetings_count + ' percentage: ' + member.meetings_percentage() + ' <em>You are allowed to miss ' + sprints.meetings_slop + meetings + '</em>' + '</p>' + '<p>Tasks completed: ' + member.completed_count + '/' + (member.completed_total / teamSize).toFixed(2) + ' for a completion factor of: ' + member.completed_factor(teamSize) + '</p>' + '<p>Reviews completed: ' + member.reviews_count + ' for a reviewing factor of: ' + member.reviewing_factor(teamSize) + '</p>';
};
var present_info = function present_info(div, sprints) {
var infoDiv = _Util__WEBPACK_IMPORTED_MODULE_2__.Util.createElement('div', 'trello-info');
div.appendChild(infoDiv);
infoDiv.innerHTML = '<p>The completion factor for tasks is based on a metric that every' + ' team member is expected to complete ' + (sprints.completed_factor * 100).toFixed(0) + '% of' + ' an equal distribution of tasks. Values less than 1.00 indicate that you will be' + ' losing points on the assignment.</p>' + '<p>The reviewing factor for tasks is based on a metric that every team member' + ' is expected to review ' + (sprints.reviewing_factor * 100).toFixed(0) + '% of an equal' + ' distribution of tasks. This factor is based on a metric that 90% of tasks should' + ' be programming tasks. Values less than 1.00 indicate that you will be' + ' losing points on the assignment.</p>';
};
}; /// @cond
SprintView.prototype = Object.create(_DataView__WEBPACK_IMPORTED_MODULE_0__.DataView.prototype);
SprintView.prototype.constructor = SprintView; /// @endcond
/***/ }),
/***/ "./src/Sprints/Sprints.js":
/*!********************************!*\
!*** ./src/Sprints/Sprints.js ***!
\********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Sprints": () => (/* binding */ Sprints)
/* harmony export */ });
/* harmony import */ var _Sprint__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Sprint */ "./src/Sprints/Sprint.js");
/* harmony import */ var _SprintMember__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./SprintMember */ "./src/Sprints/SprintMember.js");
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
/*
* Sprint analysis of Trello board
*/
var Sprints = function Sprints(board) {
var that = this; /// Number of missed meetings allow
this.meetings_slop = 1; /// Number of seconds after meeting time to consider completed
/// in a current sprint in seconds.
this.sprint_time_slop = 5 * 60 * 60; // 5 hours
/// Each users is expected to complete 80% of his share of tasks
this.completed_factor = 0.8; /// Each users is expected to complete 80% of 90% of the task count in reviews
this.reviewing_factor = 0.8 * 0.9;
this.board = board;
this.errors = [];
this.warnings = [];
this.members = {};
this.sprints = [];
this.design = null;
this.risks = null;
this.meetings = null;
this.todo = null;
this.sprint_active = null;
this.sprint_completed = null;
this.completed = null; //
// Copy over the members
//
for (var id in board.members) {
var member = board.members[id];
if (member.name.toLowerCase() === "cse335") {
continue;
}
this.members[id] = new _SprintMember__WEBPACK_IMPORTED_MODULE_1__.SprintMember(this, member);
} //
// Find all of the required lists
//
this.find_lists();
if (this.errors.length > 0) {
this.error('e900');
return;
} //
// Order testing
//
this.order_test(); //
// Determine attendance
//
this.meeting_attendance(); //
// Convert meetings into sprints
//
this.create_sprints(); //
// Sort completed into sprints
//
this.sort_completed(); //
// Completed statistics
//
this.completed_statistics();
};
/**
* Ensure all required lists exist.
*/
Sprints.prototype.find_lists = function () {
// Find the "Design" list
this.design = this.board.find_list('Design');
if (this.design === null) {
this.error('e001');
} // Find the "Risks" list
this.risks = this.board.find_list('Risks');
if (this.risks === null) {
this.error('e002');
} // Find the "Meetings" list
this.meetings = this.board.find_list('Meetings');
if (this.meetings === null) {
this.error('e003');
} // Find the "To Do" list
this.todo = this.board.find_list('To Do');
if (this.todo === null) {
this.error('e004');
} // Find the "This Sprint Active" list
this.sprint_active = this.board.find_list('This Sprint Active');
if (this.sprint_active === null) {
this.error('e005');
} // Find the "This Sprint Completed" list
this.sprint_completed = this.board.find_list('This Sprint Completed');
if (this.sprint_completed === null) {