Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: select all for add member in group #218

Open
wants to merge 3 commits into
base: ui-improvements
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
9 changes: 7 additions & 2 deletions Access/group_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,14 +447,19 @@ def add_user_to_group(request):
"msg": NON_OWNER_PERMISSION_DENIED_ERROR["msg"],
}
return context
selected_users_list = []
is_select_all = json.loads(data.get("selectAllUsers")) if data.get("selectAllUsers") else False

selected_users_list = json.loads(data.get("selectedUserList"))
if is_select_all:
selected_users_list = list(map(lambda user: user["email"], request.user.user.get_active_users().values('email')))
if not selected_users_list and data.get("selectedUserList"):
selected_users_list = json.loads(data.get("selectedUserList"))

duplicate_request_emails = _check_if_members_in_group(
group=group, selected_members=selected_users_list
)

if duplicate_request_emails:
if duplicate_request_emails and not is_select_all:
context = {}
msg = DUPLICATE_GROUP_MEMBER_ADD_REQUEST.format(
user_emails=duplicate_request_emails
Expand Down
4 changes: 4 additions & 0 deletions Access/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,10 @@ def get_system_user():
email="[email protected]")
return django_user.user

def get_active_users(self):
""" method to get active users """
return User.objects.filter(state='1').exclude(user=self.user)

def __str__(self):
return f"{self.user}"

Expand Down
101 changes: 81 additions & 20 deletions static/js/addUserToGroup.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const userSelectedList = {};
var userSelectedList = {};
var disabled = false;
const USER_SELECTION_LIMIT = 20;

const handleUserSelectionCheckbox = (elem) => {
$(elem).prop('checked', !$(elem).prop('checked'));
Expand All @@ -7,6 +9,9 @@ const handleUserSelectionCheckbox = (elem) => {
const handleSelectionView = () => {

let finalCount = $('#user-selection-table').children('tr').length
if(disabled) {
finalCount = "All";
}

if(finalCount < 1) {
$('#user-selection-list').children('nav').hide();
Expand Down Expand Up @@ -62,18 +67,32 @@ const removeUserSelection = (elem) => {

const removeUserSelectionUI = (elem) => {
rightElem = elem.parentElement.parentElement;
$("#selectAllUsers").prop("checked", false);
removeSelectionSpanElem(rightElem, $("#user-table").find(`tr[email="${$(rightElem).attr('email')}"]`));
updateSelectedUser();
if($(rightElem).attr("selectAll")) {
$("#selectAllUsers").prop("checked", false);
disabled = false;
handleDisableMode();
$(rightElem).remove();
handleSelectionView();
} else {
removeSelectionSpanElem(rightElem, $("#user-table").find(`tr[email="${$(rightElem).attr('email')}"]`));
}
$('#max-member-selected-warning').hide();
};

const removeAllUsers = () => {
const removeAllUsers = (disabledState) => {
disabled = disabledState;
const users = $('#user-selection-table').children('tr');
$("#selectAllUsers").prop("checked", false);
for(iter = 0; iter < users.length; iter++) {
removeSelectionSpanElem(users[iter], $("#user-table").find(`tr[email="${$(users[iter]).attr('email')}"]`));
if ($(users[iter]).attr('selectAll')) {
$("#selectAllUsers").prop("checked", false);
$(users[iter]).remove();
} else {
removeSelectionSpanElem(users[iter], $("#user-table").find(`tr[email="${$(users[iter]).attr('email')}"]`));
}
}
updateSelectedUser();
handleDisableMode();
handleSelectionView();
$('#max-member-selected-warning').hide();
};

function updateSelectedUser() {
Expand All @@ -87,40 +106,82 @@ function updateSelectedUser() {
}

const selectAllUsers = () => {
const users = $('#user-table').children('tr');
for(iter = 0; iter < users.length; iter++) {
if(!userSelectedList[$(users[iter]).attr('email')]) {
addUserSelection(users[iter]);
}
}
updateSelectedUser();
removeAllUsers(true);
const selectionList = $('#user-selection-table');
const newSpan = $("#user-selection-row-template").clone(true, true);
newSpan.appendTo(selectionList);
newSpan.show();
const tableData = newSpan.children('td');
tableData[0].textContent = "All User Selected";
newSpan.attr("selectAll", true);
handleSelectionView();
}

const selectAllUserToggle = (elem) => {
if(elem.checked) {
selectAllUsers();
} else {
removeAllUsers();
removeAllUsers(false);
}
}

const findUserSelectedListLength = () => {
let count = 0;
Object.values(userSelectedList).forEach(val => {
if(val) count++;
})
return count;
}

const handleUserSelection = (elem) => {
if(disabled) return;
if(!$(elem).find('input').prop('checked')) {
if(findUserSelectedListLength() === USER_SELECTION_LIMIT) {
$('#max-member-selected-warning').show();
return;
}
addUserSelection(elem);
} else {
removeUserSelection(elem);
}
updateSelectedUser();
if(findUserSelectedListLength() === USER_SELECTION_LIMIT) {
$('#max-member-selected-warning').show();
} else {
$('#max-member-selected-warning').hide();
}
};

const handleDisableMode = () => {
selectedList = {};
const users = $('#user-table').children('tr');
for (iter = 0; iter < users.length; iter++) {
if (disabled) {
$(users[iter]).find('input').prop('checked', true);
$(users[iter]).removeAttr("onclick");
$(users[iter]).find('input').attr("disabled", true);
$(users[iter]).removeClass('hover:bg-blue-50 hover:text-blue-700').addClass('bg-gray-50');
$(users[iter]).children('td#description-td').removeClass('text-gray-900').addClass('text-blue-600');
} else {
$(users[iter]).attr("onclick", "handleUserSelection(this)");
$(users[iter]).find('input').attr("disabled", false);
$(users[iter]).find('input').prop('checked', false);
$(users[iter]).children('td#description-td').addClass('text-gray-900').removeClass('text-blue-600');
$(users[iter]).addClass('hover:bg-blue-50 hover:text-blue-700').removeClass('bg-gray-50');
}
}
}

function submitRequest(event, elem) {
event.preventDefault();
form = $(elem);
let actionUrl = form.attr('action');
const selectAllUsers = $("#selectAllUsers").prop("checked");
requestData = form.serialize() + "&selectAllUsers=" + selectAllUsers;
$.ajax({
type: "POST",
url: actionUrl,
data: form.serialize(),
data: requestData,
error: (xhr, statusText, data) => {
if(xhr.responseJSON) {
showNotification("failed", xhr.responseJSON["error"]["msg"], xhr.responseJSON["error"]["error_msg"]);
Expand Down Expand Up @@ -161,12 +222,12 @@ function update_users(search, page, groupName) {
$("#user-table tr").remove();

const rows = users.map((user) => {
return `<tr onclick="handleUserSelection(this)" email="${user["email"]}" user_name="${user["first_name"]} ${user["last_name"]}" class="${userSelectedList[user["email"]]? "bg-gray-50": "hover:bg-blue-50 hover:text-blue-700"}">
return `<tr onclick="handleUserSelection(this)" email="${user["email"]}" user_name="${user["first_name"]} ${user["last_name"]}" class="${(userSelectedList[user["email"]] || disabled)? "bg-gray-50": "hover:bg-blue-50 hover:text-blue-700"}">
<td class="relative w-12 px-6 sm:w-16 sm:px-8">
<input type="checkbox" id="adduser-checkbox-td" value="${user["email"]}"
class="absolute left-4 top-1/2 -mt-2 h-4 w-4 rounded border-gray-300 focus:ring-blue-500 sm:left-6" ${ userSelectedList[user["email"]]? "checked": "" } onclick="handleUserSelectionCheckbox(this)"></input>
class="absolute left-4 top-1/2 -mt-2 h-4 w-4 rounded border-gray-300 focus:ring-blue-500 sm:left-6" ${ (userSelectedList[user["email"]] || disabled)? "checked": "" } onclick="handleUserSelectionCheckbox(this)" ${(disabled) ? "disabled" : ""}></input>
</td>
<td id="adduser-description-td" class="whitespace-nowrap py-4 pr-3 text-sm font-normal ${ userSelectedList[user["email"]]? "text-blue-600" : "text-gray-900"}">
<td id="adduser-description-td" class="whitespace-nowrap py-4 pr-3 text-sm font-normal ${ (userSelectedList[user["email"]] || disabled)? "text-blue-600" : "text-gray-900"}">
${user["first_name"]} ${user["last_name"]} ${user["email"]}</td>
</tr>`;
})
Expand Down
11 changes: 8 additions & 3 deletions templates/EnigmaOps/addUserToGroupForm.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{% extends 'global_layout.html' %}
{% load static %}
{% load reusable_components %}

{% block head_body %}
<script src={% static "js/addUserToGroup.js" %}></script>
Expand Down Expand Up @@ -75,6 +76,10 @@ <h1 id="groupNameHeading" class="text-2xl font-bold text-gray-900" groupName="{{
</div>
</div>

<div id="max-member-selected-warning" class="hidden">
{% get_error_panel_with_message "Max number of members selected" "Deselect some selections or Submit request to select more members." %}
</div>

<h1 class="pt-8 text-sm leading-5 font-medium text-gray-900">Add members</h1>
<div class="grid grid-cols-2 gap-4">
<div class="flex-col">
Expand All @@ -90,8 +95,8 @@ <h1 class="pt-8 text-sm leading-5 font-medium text-gray-900">Add members</h1>
</div>

<div class="flex-none flex">
<input type="checkbox" onclick="selectAllUserToggle(this)" name="select-all-user" id="selectAllUsers" class="ml-4 mr-2 mt-2 px-1 py-1 top-1/2 h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-600 sm:left-6">
<label class="ml-1 mr-3 mt-1 mb-2 text-base leading-6 font-normal text-gray-900">Select all</label>
<input type="checkbox" onclick="selectAllUserToggle(this)" name="selectAllUsers" id="selectAllUsers" class="ml-4 mr-2 mt-2 px-1 py-1 top-1/2 h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-600 sm:left-6">
<label for="selectAllUsers" class="ml-1 mr-3 mt-1 mb-2 text-base leading-6 font-normal text-gray-900">Select all</label>
</div>
</div>

Expand Down Expand Up @@ -143,7 +148,7 @@ <h1 class="text-lg leading-7 font-medium text-gray-900">All group members</h1>
</table>
</div>
<nav class="flex flex-shrink-0 px-4 items-center justify-between align-bottom border-t border-gray-200 pt-2 pb-2 hidden">
<button type="button" class="inline-flex items-center rounded-md border border-transparent bg-blue-100 px-4 py-2 text-base font-medium text-blue-700 shadow-sm hover:bg-blue-200 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:ring-offset-2" onclick="removeAllUsers();">
<button type="button" class="inline-flex items-center rounded-md border border-transparent bg-blue-100 px-4 py-2 text-base font-medium text-blue-700 shadow-sm hover:bg-blue-200 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:ring-offset-2" onclick="removeAllUsers(false);">
Remove all new
</button>
</nav>
Expand Down