Last active
December 26, 2017 11:38
-
-
Save EvAlex/2d739db7f084a193154aac7027ce3a8f to your computer and use it in GitHub Desktop.
Jira - users remaining till license limit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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