* target modal content by a classname to avoid duplicate IDs * woops - fix missed selector * use showWindowModal in editUser * move add org to a partial * move add role into a partial * move adjust credits to a partial * move profile modals to be re-used * generalise approach to add organisation modal * generalise add role modal form * generalise adjust credits modal * rework unpublish modal * refactor banish user modal * refactors * prevent issues with duplicate ids * fix banish form action * make sure role management specs covered in cypress * let hidden modal content use IDs * rename file for clarity * add some JSDoc notes * cleanup some redundant changes * one more * woops - fixed id that contained a classname
185 lines
5.8 KiB
JavaScript
185 lines
5.8 KiB
JavaScript
import { WINDOW_MODAL_ID, showWindowModal } from '@utilities/showModal';
|
|
|
|
const getModalContent = () => document.getElementById(WINDOW_MODAL_ID);
|
|
|
|
/**
|
|
* Populate the add organization modal with user data
|
|
*
|
|
* @param {Object} dataset
|
|
* @param {string} dataset.userName
|
|
* @param {string} dataset.userId
|
|
*/
|
|
const initializeAddOrganizationContent = ({ userName, userId }) => {
|
|
const modalContent = getModalContent();
|
|
|
|
modalContent.querySelector('#organization_membership_user_id').value =
|
|
parseInt(userId, 10);
|
|
|
|
modalContent.querySelector('.js-user-name').innerText = userName;
|
|
};
|
|
|
|
/**
|
|
* Populate the add role modal with its action
|
|
*
|
|
* @param {Object} dataset
|
|
* @param {string} dataset.formAction The URL for the form action
|
|
*/
|
|
const initializeAddRoleContent = ({ formAction }) => {
|
|
getModalContent().querySelector('.js-add-role-form').action = formAction;
|
|
};
|
|
|
|
/**
|
|
* Populate the adjust credits modal with user data
|
|
*
|
|
* @param {Object} dataset
|
|
* @param {string} dataset.userName
|
|
* @param {string} dataset.unspentCreditsCount The user's current credit balance
|
|
* @param {string} dataset.formAction The URL for the form action
|
|
*/
|
|
const initializeAdjustCreditBalanceContent = ({
|
|
userName,
|
|
unspentCreditsCount,
|
|
formAction,
|
|
}) => {
|
|
const modalContent = getModalContent();
|
|
|
|
const form = modalContent.querySelector('.js-adjust-credits-form');
|
|
form.action = formAction;
|
|
|
|
const canRemoveCredits = unspentCreditsCount > 0;
|
|
if (canRemoveCredits) {
|
|
const remove = document.createElement('option');
|
|
remove.value = 'Remove';
|
|
remove.innerText = 'Remove';
|
|
|
|
modalContent.querySelector('.js-credit-action').appendChild(remove);
|
|
}
|
|
|
|
modalContent.querySelector('.js-user-name').innerText = userName;
|
|
modalContent.querySelector('.js-unspent-credits-count').innerText =
|
|
unspentCreditsCount;
|
|
modalContent.querySelector('.js-credit-amount').dataset.unspentCredits =
|
|
unspentCreditsCount;
|
|
|
|
form.addEventListener('change', ({ target: { value, name, form } }) => {
|
|
if (name === 'user[credit_action]') {
|
|
const creditAmount = form['user[credit_amount]'];
|
|
|
|
if (value === 'Add') {
|
|
if (creditAmount.getAttribute('data-old-max')) {
|
|
creditAmount.setAttribute(
|
|
'max',
|
|
creditAmount.getAttribute('data-old-max'),
|
|
);
|
|
}
|
|
} else {
|
|
creditAmount.setAttribute(
|
|
'data-old-max',
|
|
creditAmount.getAttribute('max'),
|
|
);
|
|
creditAmount.setAttribute('max', creditAmount.dataset.unspentCredits);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Populate the unpublish all posts model with user data
|
|
*
|
|
* @param {Object} dataset
|
|
* @param {string} dataset.formAction The URL for the form action
|
|
* @param {string} dataset.userName
|
|
*/
|
|
const initializeUnpublishAllPostsContent = ({ formAction, userName }) => {
|
|
const modalContent = getModalContent();
|
|
modalContent.querySelector('.js-unpublish-form').action = formAction;
|
|
modalContent
|
|
.querySelectorAll('.js-user-name')
|
|
.forEach((span) => (span.innerText = userName));
|
|
};
|
|
|
|
/**
|
|
* Populate the banish modal with user data
|
|
*
|
|
* @param {Object} dataset
|
|
* @param {string} dataset.formAction The URL for the form action
|
|
* @param {string} dataset.userName
|
|
* @param {string} dataset.banishableUser "true" or "false" - is it possible to banish this user
|
|
*/
|
|
const initializeBanishContent = ({ formAction, userName, banishableUser }) => {
|
|
const modalContent = getModalContent();
|
|
|
|
const banishable = banishableUser === 'true';
|
|
const banishableContent = modalContent.querySelector('.js-banishable-user');
|
|
const notBanishableContent = modalContent.querySelector(
|
|
'.js-not-banishable-user',
|
|
);
|
|
|
|
if (banishable) {
|
|
banishableContent.classList.remove('hidden');
|
|
notBanishableContent.classList.add('hidden');
|
|
modalContent.querySelector('.js-banish-form').action = formAction;
|
|
} else {
|
|
banishableContent.classList.add('hidden');
|
|
notBanishableContent.classList.remove('hidden');
|
|
}
|
|
|
|
modalContent
|
|
.querySelectorAll('.js-user-name')
|
|
.forEach((span) => (span.innerText = userName));
|
|
};
|
|
|
|
const modalContentInitializers = {
|
|
'#add-organization': initializeAddOrganizationContent,
|
|
'#add-role-modal': initializeAddRoleContent,
|
|
'#adjust-balance': initializeAdjustCreditBalanceContent,
|
|
'#unpublish-all-posts': initializeUnpublishAllPostsContent,
|
|
'#banish-for-spam': initializeBanishContent,
|
|
};
|
|
|
|
const modalContents = new Map();
|
|
/**
|
|
* Helper function to handle finding and caching modal content. Since our Preact modal helper works by duplicating HTML content,
|
|
* and our user modals rely on IDs to label form controls, we remove the original hidden content from the DOM to avoid ID conflicts.
|
|
*
|
|
* @param {string} modalContentSelector The CSS selector used to identify the correct modal content
|
|
*/
|
|
const getModalContents = (modalContentSelector) => {
|
|
if (!modalContents.has(modalContentSelector)) {
|
|
const modalContentElement = document.querySelector(modalContentSelector);
|
|
const modalContent = modalContentElement.innerHTML;
|
|
|
|
modalContentElement.remove();
|
|
modalContents.set(modalContentSelector, modalContent);
|
|
}
|
|
|
|
return modalContents.get(modalContentSelector);
|
|
};
|
|
|
|
/**
|
|
* Helper function for views which use admin user modals. May be attached as an event listener, and its actions will only be triggered
|
|
* if the target of the event is a recognised user modal trigger.
|
|
*
|
|
* @param {Object} event
|
|
*/
|
|
export const showUserModal = (event) => {
|
|
const { dataset } = event.target;
|
|
|
|
if (!Object.prototype.hasOwnProperty.call(dataset, 'modalContentSelector')) {
|
|
// We're not trying to trigger a modal.
|
|
return;
|
|
}
|
|
|
|
event.preventDefault();
|
|
|
|
const { modalTitle, modalSize, modalContentSelector } = dataset;
|
|
|
|
showWindowModal({
|
|
modalContent: getModalContents(modalContentSelector),
|
|
title: modalTitle,
|
|
size: modalSize,
|
|
onOpen: () => {
|
|
modalContentInitializers[modalContentSelector]?.(dataset);
|
|
},
|
|
});
|
|
};
|