docbrown/app/javascript/packs/admin/users/memberIndex.js
2022-04-14 18:19:28 +02:00

125 lines
3.7 KiB
JavaScript

import { openDropdown, closeDropdown } from '@utilities/dropdownUtils';
import { copyToClipboard } from '@utilities/runtime';
import { showWindowModal, closeWindowModal } from '@utilities/showModal';
// We present up to 50 users in the UI at once, and for performance reasons we don't want to add individual click listeners to each dropdown menu or inner menu item
// Instead we listen for click events anywhere in the table, and identify required actions based on data attributes of the target
document
.getElementById('member-index-content')
?.addEventListener('click', ({ target }) => {
const {
dataset: { copyEmail, toggleDropdown },
} = target;
if (copyEmail) {
handleEmailCopy(copyEmail);
return;
}
if (toggleDropdown) {
handleDropdownToggle({
triggerElementId: target.getAttribute('id'),
dropdownContentId: toggleDropdown,
});
return;
}
});
// We keep track of the currently opened dropdown to make sure we only ever have one open at a time
let currentlyOpenDropdownId;
const handleDropdownToggle = ({ triggerElementId, dropdownContentId }) => {
const triggerButton = document.getElementById(triggerElementId);
const isCurrentlyOpen =
triggerButton.getAttribute('aria-expanded') === 'true';
if (isCurrentlyOpen) {
closeDropdown({ triggerElementId, dropdownContentId });
triggerButton.focus();
currentlyOpenDropdownId = null;
} else {
closeCurrentlyOpenDropdown();
openDropdown({ triggerElementId, dropdownContentId });
currentlyOpenDropdownId = dropdownContentId;
}
};
/**
* Make sure any currently opened dropdown is closed
*/
const closeCurrentlyOpenDropdown = (focusTrigger = false) => {
if (!currentlyOpenDropdownId) {
return;
}
const triggerButton = document.querySelector(
`[aria-controls='${currentlyOpenDropdownId}']`,
);
closeDropdown({
dropdownContentId: currentlyOpenDropdownId,
triggerElementId: triggerButton?.getAttribute('id'),
});
if (focusTrigger) {
triggerButton.focus();
}
};
// We listen for key up events on this page to make sure users can close the dropdowns via keyboard
document.addEventListener('keyup', ({ key }) => {
if (key === 'Escape') {
closeCurrentlyOpenDropdown(true);
return;
}
if (key === 'Tab') {
// If we're not inside a dropdown any more, let's close it
const closestDropdown = document.activeElement.closest('.crayons-dropdown');
if (!closestDropdown) {
closeCurrentlyOpenDropdown();
}
}
});
/**
* Helper function to copy the given text to the clipboard and display a snackbar confirmation.
*
* @param {string} copyEmail The email to copy
*/
const handleEmailCopy = (copyEmail) => {
copyToClipboard(copyEmail)
.then(() => {
document.dispatchEvent(
new CustomEvent('snackbar:add', {
detail: { message: 'Copied to clipboard' },
}),
);
closeCurrentlyOpenDropdown(true);
})
.catch(() => {
document.dispatchEvent(
new CustomEvent('snackbar:add', {
detail: {
message: 'Unable to copy the text. Try reloading the page',
},
}),
);
});
};
// The reason that we loop through the elements is because we have alternate layouts
// for different screen sizes
document.querySelectorAll('.js-export-csv-modal-trigger').forEach((item) => {
item.addEventListener('click', () => {
showWindowModal({
title: 'Download Member Data',
contentSelector: '#export-csv-modal',
overlay: true,
onOpen: () => {
document
.querySelector('#window-modal .js-export-csv-modal-cancel')
?.addEventListener('click', closeWindowModal);
},
});
});
});