Skip to content

Instantly share code, notes, and snippets.

@EvAlex
Last active December 26, 2017 11:38
Show Gist options
  • Save EvAlex/2d739db7f084a193154aac7027ce3a8f to your computer and use it in GitHub Desktop.
Save EvAlex/2d739db7f084a193154aac7027ce3a8f to your computer and use it in GitHub Desktop.
Jira - users remaining till license limit
/**
* Useful when you have more users in Jira than your license limit allows and some of them are inactive.
* Say, you have 89 users, while your license allows only 50. Some of current users are inactive.
* You hired 2 people and want to find out whether there's enough room for them. And if not - which users
* are candidates for removal. Problem is there's no "only active" filter and no sorting by last login date
* on users page in Jira. This script helps solve these problems.
*
* To use this script:
* - go to Administration in your Jira
* - go to Users page
* - select "All" for "Users Per Page"
* - open dev tools in your browser
* - copy-paste and run this script
*
* Tested on Jira v5.2.10#853-sha1:c0ba268
*/
class User {
static fromUsersTableRow(tr) {
var result = new User(),
usernameEl = tr.getElementsByClassName('username')[0],
username = usernameEl ? usernameEl.innerText.replace('\n(Inactive)', '') : null,
fullnameEl = tr.getElementsByClassName('fn')[0],
fullname = fullnameEl ? fullnameEl.innerText : null,
emailEl = tr.getElementsByClassName('fn')[0],
email = emailEl ? emailEl.innerText : null,
loginDetailsEl = tr.querySelector('[data-cell-type="login-details"]'),
userGroupsEls = tr.querySelectorAll('[data-cell-type="user-groups"] a');
result.username = username;
result.active = !tr.querySelector('del');
result.fullname = fullname;
result.email = email;
result.loginDetails = loginDetailsEl
? LoginDetails.fromLoginDetailsTableCell(loginDetailsEl)
: null;
result.userGroups = [];
for (var i = 0; i < userGroupsEls.length; i++) {
result.userGroups.push(userGroupsEls[i].textContent);
}
return result;
}
}
class LoginDetails {
constructor(count, last) {
this.count = count;
this.last = last;
}
static fromLoginDetailsTableCell(td) {
var result = new LoginDetails();
var childNodes = [];
for (var i = 0; i < td.childNodes.length; i++) {
childNodes.push(td.childNodes[i]);
}
childNodes = childNodes.filter(e => e.nodeName === 'STRONG'
|| e.nodeName === 'TEXT' && e.textContent.replace(/\s/g, '').length > 0);
return new LoginDetails(childNodes[1] || null, new Date(childNodes[2]) || null);
}
}
function getUsersSummary(licensedUsersCount) {
const userRows = document.getElementsByClassName('user-row'),
users = [];
for (const userRow of userRows) {
users.push(User.fromUsersTableRow(userRow));
}
const activeUsers = users.filter(e => e.active);
const inactiveUsers = users.filter(e => !e.active);
let summary = `Total users: ${userRows.length}\nActive users: ${activeUsers.length}\n\n`,
vacantCount = licensedUsersCount - activeUsers.length;
if (vacantCount > 2) {
summary += 'There is room for extra ' + vacantCount + ' users';
} else {
summary += 'There is no room for extra users. Deactivate existing ones or extend your license.\n\n';
const topInactiveSliceCount = 5;
const topInactive = activeUsers.sort((a, b) => a.loginDetails.last.getTime() - b.loginDetails.last.getTime()).slice(0, topInactiveSliceCount);
const topInactiveStrings = topInactive.map(e => `${e.username} (${e.loginDetails.last.toDateString()})`);
summary += `Top ${topInactiveSliceCount} inactive users that logged in long ago:\n- ${topInactiveStrings.join('\n- ')}`;
}
return summary;
}
const licensedUsersCount = 50;
const summary = getUsersSummary(licensedUsersCount);
console.log(summary);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment