* gotta commit at some point * out of gas * IT'S WORKING NOW! 💥 * Cypress tests * fix Travis failures * incorporate PR review suggestions * fix one failing Cypress test * update API call * add Unsuspend flow; fix Travis failures * add tests for unsuspend flow * remove unnecessary atrribute * add article_policy spec * fix failing Travis * nudge Travis * fix apparent typo o o 🤷 * refactor a bunch of duplication * nudge Travis * fix Cypress failure related to authorizing moderator for user_status action * rename modal partial * remove unnecessary button-exists check * address PR review suggestions * hide suspend user btn after action * toggle btn based on author suspension status * add data-testids * use data-testids * controller refactor
144 lines
4 KiB
JavaScript
144 lines
4 KiB
JavaScript
import {
|
|
closeWindowModal,
|
|
showWindowModal,
|
|
WINDOW_MODAL_ID,
|
|
} from '@utilities/showModal';
|
|
import { request } from '@utilities/http';
|
|
|
|
const suspendOrUnsuspendUser = async ({
|
|
event,
|
|
btnAction,
|
|
userId,
|
|
username,
|
|
suspendOrUnsuspendReason,
|
|
}) => {
|
|
event.preventDefault();
|
|
closeModal();
|
|
|
|
try {
|
|
const response = await request(
|
|
`/admin/member_manager/users/${userId}/user_status`,
|
|
{
|
|
method: 'PATCH',
|
|
body: JSON.stringify({
|
|
id: userId,
|
|
user: {
|
|
note_for_current_role: suspendOrUnsuspendReason,
|
|
user_status: btnAction == 'suspend' ? 'Suspended' : 'Good standing',
|
|
},
|
|
}),
|
|
credentials: 'same-origin',
|
|
},
|
|
);
|
|
|
|
const outcome = await response.json();
|
|
|
|
if (outcome.success) {
|
|
top.addSnackbarItem({
|
|
message: outcome.message,
|
|
addCloseButton: true,
|
|
});
|
|
|
|
updateBtnFlow(btnAction, username);
|
|
} else {
|
|
top.addSnackbarItem({
|
|
message: 'Error: something went wrong.',
|
|
addCloseButton: true,
|
|
});
|
|
}
|
|
} catch (error) {
|
|
top.addSnackbarItem({
|
|
message: `Error: ${error}`,
|
|
addCloseButton: true,
|
|
});
|
|
}
|
|
};
|
|
|
|
function capitalizeFirst(string) {
|
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
}
|
|
|
|
function updateBtnFlow(btnAction, username) {
|
|
const btn = window.parent.document
|
|
.getElementById('mod-container')
|
|
.contentDocument.querySelector(`#${btnAction}-user-btn`);
|
|
const oppositeAction = btnAction == 'suspend' ? 'unsuspend' : 'suspend';
|
|
|
|
btn.textContent = `${capitalizeFirst(oppositeAction)} ${username}`;
|
|
btn.dataset.modalTitle = `${capitalizeFirst(oppositeAction)} ${username}`;
|
|
btn.id = `${oppositeAction}-user-btn`;
|
|
btn.dataset.modalContentSelector = `#${oppositeAction}-modal-content`;
|
|
|
|
oppositeAction == 'suspend'
|
|
? btn.classList.add('c-btn--destructive')
|
|
: btn.classList.remove('c-btn--destructive');
|
|
}
|
|
|
|
function closeModal() {
|
|
closeWindowModal(window.parent.document);
|
|
}
|
|
|
|
// let modalContents;
|
|
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 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 =
|
|
window.parent.document.querySelector(modalContentSelector);
|
|
const modalContent = modalContentElement.innerHTML;
|
|
|
|
modalContentElement.remove();
|
|
modalContents.set(modalContentSelector, modalContent);
|
|
}
|
|
|
|
return modalContents.get(modalContentSelector);
|
|
};
|
|
|
|
function checkReason(event) {
|
|
const { btnAction, reasonSelector, userId, username } = event.target.dataset;
|
|
const modal = window.parent.document.getElementById(WINDOW_MODAL_ID);
|
|
const actionReason = modal.querySelector(reasonSelector).value;
|
|
|
|
if (!actionReason) {
|
|
modal.querySelector(`.${btnAction}-reason-error`).innerText =
|
|
'You must give a reason for this action.';
|
|
} else {
|
|
suspendOrUnsuspendUser({
|
|
event,
|
|
btnAction,
|
|
userId,
|
|
username,
|
|
actionReason,
|
|
});
|
|
}
|
|
}
|
|
|
|
function activateModalSubmitBtn() {
|
|
const suspendBtn = window.parent.document.getElementById(
|
|
'submit-user-suspend-btn',
|
|
);
|
|
const unsuspendBtn = window.parent.document.getElementById(
|
|
'submit-user-unsuspend-btn',
|
|
);
|
|
|
|
suspendBtn?.addEventListener('click', checkReason);
|
|
unsuspendBtn?.addEventListener('click', checkReason);
|
|
}
|
|
|
|
export function toggleModal(event) {
|
|
event.preventDefault;
|
|
const { modalTitle, modalSize, modalContentSelector } = event.target.dataset;
|
|
showWindowModal({
|
|
document: window.parent.document,
|
|
modalContent: getModalContents(modalContentSelector),
|
|
title: modalTitle,
|
|
size: modalSize,
|
|
onOpen: activateModalSubmitBtn,
|
|
});
|
|
}
|