░▒▓████████████████████████████████▓▒░ ░▒▓█ ▓▒░ ░▒▓█ ~ S W A M P ~ ▓▒░ ░▒▓█ ▓▒░ ░▒▓████████████████████████████████▓▒░
pplmvsvm
LOCATION:
/var/www/moodle/public/grade/penalty/duedate/amd/src
☗ ROOT
↻ REFRESH
✎ CARVE FLESH
EDITING: edit_penalty_form.js
// This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Handles edit penalty form. * * @module gradepenalty_duedate/edit_penalty_form * @copyright 2024 Catalyst IT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ import * as notification from 'core/notification'; import Fragment from 'core/fragment'; import Templates from 'core/templates'; /** * Rule js class. */ class PenaltyRule { constructor( overdueby = 0, penalty = 0, ) { this.overdueby = overdueby; this.penalty = penalty; } } /** * Selectors */ const SELECTORS = { FORM_CONTAINER: '#penalty_rule_form_container', ACTION_MENU: '.action-menu', ADD_BUTTON: '#addrulebutton', INSERT_BUTTON: '.insertbelow', DELETE_BUTTON: '.deleterulebuttons', DELETE_ALL_BUTTON_CONTAINER: '#deleteallrulesbuttoncontainer', }; /** * Register click event for delete and insert buttons. */ const registerEventListeners = () => { // Find all action menus in penalty rule form. const container = document.querySelector(SELECTORS.FORM_CONTAINER); container.addEventListener('click', (e) => { if (e.target.closest(SELECTORS.DELETE_BUTTON)) { e.preventDefault(); deleteRule(e.target); return; } if (e.target.closest(SELECTORS.INSERT_BUTTON)) { e.preventDefault(); insertRule(e.target); return; } }); document.querySelector(SELECTORS.ADD_BUTTON).addEventListener('click', (e) => { e.preventDefault(); insertRuleAtIndex(container.querySelectorAll(SELECTORS.ACTION_MENU).length); return; }); }; /** * Delete a rule group represented by thenode. * * @param {NodeElement} target */ const deleteRule = (target) => { // Get all form data. const {contextid, penaltyRules, finalPenaltyRule} = buildFormParams(); const ruleNumber = getRuleNumber(target); // Remove the penalty rule. const updatedPenaltyRules = penaltyRules.filter((rule, index) => index !== ruleNumber); loadPenaltyRuleForm( contextid, updatedPenaltyRules, finalPenaltyRule, ); }; /** * Insert a rule group below the clicked button. * * @param {NodeElement} target */ const insertRule = (target) => insertRuleAtIndex(getRuleNumber(target) + 1); /** * Add a new rule group at the specified index. * * @param {Number} ruleNumber */ const insertRuleAtIndex = (ruleNumber) => { // Get all form data. const {contextid, penaltyRules, finalPenaltyRule} = buildFormParams(); // Insert a new penalty rule. penaltyRules.splice(ruleNumber, 0, new PenaltyRule()); loadPenaltyRuleForm( contextid, penaltyRules, finalPenaltyRule, ); }; /** * Get the rule number from the target. * * @param {Object} target * @return {Number} rule number */ const getRuleNumber = (target) => { const allRules = target .closest(SELECTORS.FORM_CONTAINER) .querySelectorAll(SELECTORS.ACTION_MENU); const foundIndex = Array.prototype.findIndex.call( allRules, (element) => element.contains(target), ); if (foundIndex === -1) { throw new Error('Rule number not found on target', target); } return foundIndex; }; /** * Build form parameters for loading fragment. * * @return {Object} form params */ const buildFormParams = () => { // Get the penalty rule form in its container. const container = document.querySelector(SELECTORS.FORM_CONTAINER); const form = container.querySelector('form'); // Get all form data const formData = new FormData(form); // Get context id. const contextid = formData.get('contextid'); // Get group count. const groupCount = formData.get('rulegroupcount'); // Create list of penalty rules. const penaltyRules = []; // Current penalty rules. for (let i = 0; i < groupCount; i++) { penaltyRules.push(new PenaltyRule( formData.get(`overdueby[${i}][number]`) * formData.get(`overdueby[${i}][timeunit]`), formData.get(`penalty[${i}]`) )); } return { contextid, penaltyRules, finalPenaltyRule: formData.get('finalpenaltyrule'), }; }; /** * Load the penalty rule form. * * @param {Number} contextId * @param {Array} penaltyRules * @param {Number} finalPenaltyRule */ const loadPenaltyRuleForm = ( contextId, penaltyRules, finalPenaltyRule, ) => { // Disable the form while loading to improve UX. const container = document.querySelector(SELECTORS.FORM_CONTAINER); const form = container.querySelector('form'); form.querySelectorAll('input, select').forEach(input => { input.disabled = true; }); // Disable the add rule button. const addButton = document.querySelector(SELECTORS.ADD_BUTTON); if (addButton) { addButton.disabled = true; } // Disable the delete all rules button. const deleteAllButton = document.querySelector(SELECTORS.DELETE_ALL_BUTTON_CONTAINER).querySelector('button'); if (deleteAllButton) { deleteAllButton.disabled = true; } // Replace the form with the new form. Fragment.loadFragment( 'gradepenalty_duedate', 'penalty_rule_form', contextId, { penaltyrules: JSON.stringify(penaltyRules), finalpenaltyrule: finalPenaltyRule, }, ) .then((html, js) => { Templates.replaceNodeContents(document.querySelector(SELECTORS.FORM_CONTAINER), html, js); if (addButton) { addButton.disabled = false; } if (deleteAllButton) { deleteAllButton.disabled = false; } return; }) .catch(notification.exception); }; /** * Initialize the js. */ export const init = () => { registerEventListeners(); };
CANCEL
Name
Type
Size
Modified
Actions
↩ ..
DIR
—
—
📄 edit_penalty_form.js
JS
6.5 KB
2026-02-11 01:44
EDIT