Skip to content
This repository has been archived by the owner on Dec 21, 2022. It is now read-only.

Add buttons + logic to bulk select and bulk verify accounts #111

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 143 additions & 6 deletions static/js/admin.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
function generalButton (label, action, extraClass) {
var buttonDiv = document.createElement('div'),
button = document.createElement('a');
button.setAttribute('localizable', true);
button.classList.add('pure-button');
button.classList.add(label.toLowerCase().replace(/\s/g,''));
if (extraClass) {
button.classList.add(extraClass);
}
button.innerHTML = localizer.localize(label);
button.onclick = action;
buttonDiv.appendChild(button);
return buttonDiv;
}

function userButton (user, label, action, extraClass) {
var button = document.createElement('a');
button.setAttribute('localizable', true);
Expand Down Expand Up @@ -35,6 +50,96 @@ function verifyButton (user) {
);
};

function verifyUserAutomated (username, onSuccess, onError) {
SnapCloud.withCredentialsRequest(
'GET',
'/users/' + encodeURIComponent(username) +
'/verify_user/0', // token is irrelevant for admins
onSuccess,
onError,
'',
true
);
};

function htmlListUsers(userList, label) {
if (userList.length == 0) {
return "";
}
var reponse_text = "<p>The following users were " + label + ":</p>\n";
reponse_text += "<ul style=\"padding: 0;\">\n";
for (username of userList) {
// Failure usernames come with a reason of failure also: username - reason
reponse_text += "<li>" + username + "</li>\n";
}
reponse_text += "</ul>\n";
return reponse_text;
}

function verifyMultipleUsers(checkboxCollection) {
var already_verified_users = [];
var successful_users = [];
var failed_users = [];
const promises = [];
checkboxCollection.forEach(
function(user_checkbox) {
const promise = new Promise((resolve) => {
if (user_checkbox.checked) {
var username = user_checkbox.value;
verifyUserAutomated(username,
function(response) {
// Success
try {
response = JSON.parse(response);
} catch {}
if (response.state_message == "Already Verified") {
already_verified_users.push(username);
} else if (response.state_message == "New Verified") {
successful_users.push(username);
} else {
console.log("Invalid response status code", response);
}
resolve();
},
function(response) {
// Failure
failed_users.push(username + " - " + response);
resolve();
}
);
} else {
// Nothing happens to users that are not checked
resolve();
}
});
promises.push(promise);
}
);
Promise.all(promises).then(() => {
var reponse_text = ""

reponse_text += htmlListUsers(successful_users, "successfully verified");
reponse_text += htmlListUsers(already_verified_users, "already verified");
reponse_text += htmlListUsers(failed_users, "not successfully verified (failed verification)");

alert(
reponse_text,
() => { location.reload(); }
);
});
};

function verifyUser (username, onSuccess) {
SnapCloud.withCredentialsRequest(
'GET',
'/users/' + encodeURIComponent(username) +
'/verify_user/0', // token is irrelevant for admins
onSuccess,
genericError,
'Could not verify user'
);
};

function banButton (user) {
return userButton(
user,
Expand Down Expand Up @@ -338,6 +443,9 @@ function setRole (user, role) {

function basicUserDiv (user) {
var userWrapperDiv = document.createElement('div'),
userInfoCheckboxSpan = document.createElement('span'),
userInfoDiv = document.createElement('div'),
checkboxDiv = document.createElement('div'),
detailsDiv = document.createElement('div'),
usernameAnchor = userAnchor(user.username),
emailSpan = document.createElement('span'),
Expand All @@ -352,28 +460,55 @@ function basicUserDiv (user) {
user.project_count;
joinedSpan.innerHTML = '<strong localizable>Joined in </strong>' +
formatDate(user.created);

checkboxDiv.innerHTML = '<input type="checkbox" value="' + user.username +
'" name="user_checkbox" hidden=true>';
checkboxDiv.oncontextmenu = function (e) {
e.preventDefault();
if (document.getElementById("contextMenu").style.display == "block") {
hideMenu();
} else {
var menu = document.getElementById("contextMenu")
menu.style.display = 'block';
menu.style.left = e.pageX + "px";
menu.style.top = e.pageY + "px";
}
};

[ usernameAnchor, emailSpan, idSpan, projectCountSpan, joinedSpan ].forEach(
function (e) { detailsDiv.appendChild(e); }
function (e) { userInfoDiv.appendChild(e); }
);

userWrapperDiv.classList.add('user');
userWrapperDiv.classList.add('pure-u-1-2');
userInfoCheckboxSpan.classList.add('userInfoCheckbox');
userInfoDiv.classList.add('userInfo');
checkboxDiv.classList.add('checkbox');
detailsDiv.classList.add('details');

userWrapperDiv.appendChild(detailsDiv);

[ userInfoDiv, checkboxDiv ].forEach(
function (e) { userInfoCheckboxSpan.appendChild(e); }
);

userInfoDiv.style.float = "left";
checkboxDiv.style.float = "right";

detailsDiv.appendChild(userInfoCheckboxSpan);
userWrapperDiv.appendChild(detailsDiv)

return userWrapperDiv;
};

function userDiv (user) {
var userWrapperDiv = basicUserDiv(user);
detailsDiv = userWrapperDiv.querySelector('.details'),
userInfoDiv = userWrapperDiv.querySelector('.userInfo'),
detailsAndCheckbox = document.createElement('div'),
roleSpan = document.createElement('span'),
roleSelect = document.createElement('select'),
buttonsDiv = document.createElement('div');

roleSpan.innerHTML = '<strong localizable>Role</strong>:';
roleSpan.innerHTML = '<strong localizable>Role</strong>:' + ' ';
['standard', 'reviewer', 'moderator', 'admin', 'banned'].forEach(
function (role) {
var roleOption = document.createElement('option');
Expand All @@ -393,10 +528,12 @@ function userDiv (user) {

buttonsDiv.classList.add('buttons');

[ roleSpan, buttonsDiv ].forEach(
function (e) { detailsDiv.appendChild(e); }
[ roleSpan ].forEach(
function (e) { userInfoDiv.appendChild(e); }
);

detailsDiv.appendChild(buttonsDiv);

if (user.role == 'admin') {
detailsDiv.classList.add('admin');
detailsDiv.title += localizer.localize('Administrator') + '\n';
Expand Down
33 changes: 33 additions & 0 deletions static/style/admin.css
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,36 @@
.filter select:focus {
outline: none;
}

/* Checkbox Context Menu */

.checkbox-context-menu {
position: absolute;
text-align: center;
background: lightgray;
border: 1px solid black;
}

.checkbox-context-menu ul {
padding: 0px;
margin: 0px;
min-width: 85px;
list-style: none;
}

.checkbox-context-menu ul li {
margin: 0 0;
padding-bottom: 7px;
padding-top: 7px;
border: 1px solid black;
}

.checkbox-context-menu ul li a {
text-decoration: none;
color: black;
display: block;
}

.checkbox-context-menu ul li:hover {
background: darkgray;
}
23 changes: 23 additions & 0 deletions templates/checkbox_contextmenu.tmp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<div id="contextMenu" class="checkbox-context-menu" style="display:none">
<ul>
<li style="pointer-events: none;">Select</li>
<li><a href="javascript:set_checkboxes(true)">All</a></li>
<li><a href="javascript:set_checkboxes(false)">None</a></li>
</ul>
</div>

<script>
function hideMenu() {
document.getElementById(
"contextMenu").style.display = "none"
}
document.onclick = hideMenu;

function set_checkboxes(value) {
document.getElementsByName("user_checkbox").forEach(
function(e) {
e.checked = value;
}
);
}
</script>
2 changes: 1 addition & 1 deletion templates/grid.tmp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<input type="text" name="query">
<i class="fas fa-search"></i>
</form>

<script>
var ${widgetName}_page = 1,
${widgetName}_totalPages = 1,
Expand Down Expand Up @@ -118,7 +119,6 @@
callback.call(this);
}
};

</script>
</div>
@include=paginator
Expand Down
25 changes: 25 additions & 0 deletions templates/user_admin.tmp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<script src="js/admin.js"></script>
<link rel="stylesheet" href="style/admin.css">
<h1 localizable>User Administration</h1>
<div class="user_admin admin-container" style="margin-bottom: 20px;" hidden=true></div>
@param pageSize=150
@param withSearch=true
@param keepIfEmpty=true
Expand Down Expand Up @@ -63,5 +64,29 @@
}
),
paginator);
bar.insertBefore(
generalButton(
"Bulk Edit",
function () {
document.getElementsByName("user_checkbox").forEach(
function(user_checkbox) {
user_checkbox.hidden = !user_checkbox.hidden;
}
);
var admin_container = document.querySelector('.admin-container');
admin_container.hidden = !admin_container.hidden;
}
),
paginator);

var admin_select_ctrls = document.querySelector('.admin-container');
admin_select_ctrls.appendChild(
generalButton(
"Verify Selected",
() => { verifyMultipleUsers(document.getElementsByName("user_checkbox")); }
)
);

});
</script>
@include=checkbox_contextmenu