mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 16:32:18 +02:00
MDL-70760 admin: Limited length config setting validate client-side
This commit is contained in:
parent
859df15e73
commit
2375b00a08
@ -27,6 +27,8 @@
|
||||
* forceltr - always display as ltr
|
||||
* attributes - list of additional attributes containing name, value
|
||||
* readonly - bool
|
||||
* data - list of arbitrary data attributes
|
||||
* maxcharacter - maximum character
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
@ -36,12 +38,19 @@
|
||||
"size": "21",
|
||||
"forceltr": false,
|
||||
"readonly": false,
|
||||
"attributes": [ { "name": "readonly", "value": "readonly" } ]
|
||||
"attributes": [ { "name": "readonly", "value": "readonly" } ],
|
||||
"data": [ { "key": "validation_max_length", "value": "10" } ],
|
||||
"maxcharacter": false
|
||||
}
|
||||
}}
|
||||
{{!
|
||||
Setting configtext.
|
||||
}}
|
||||
<div class="form-text defaultsnext">
|
||||
<input type="text" name="{{name}}" value="{{value}}" size="{{size}}" id="{{id}}" class="form-control {{#forceltr}}text-ltr{{/forceltr}}" {{#readonly}}disabled{{/readonly}}>
|
||||
<input type="text" name="{{name}}" value="{{value}}" size="{{size}}" id="{{id}}" class="form-control {{#forceltr}}text-ltr{{/forceltr}}" {{#readonly}}disabled{{/readonly}} {{#data}} data-{{key}}={{#quote}}{{{value}}}{{/quote}}{{/data}}>
|
||||
{{#data}}
|
||||
{{#maxcharacter}}
|
||||
<div class="form-defaultinfo text-muted d-block">{{#str}} maxcharacter, admin, {{value}} {{/str}}</div>
|
||||
{{/maxcharacter}}
|
||||
{{/data}}
|
||||
</div>
|
||||
|
@ -23,3 +23,13 @@ Feature: Incoming mail configuration
|
||||
When I navigate to "Server > Email > Incoming mail configuration" in site administration
|
||||
Then "OAuth 2 service" "select" should exist
|
||||
And I should see "Testing service" in the "OAuth 2 service" "select"
|
||||
|
||||
@javascript
|
||||
Scenario: Check character limitations of mailbox name
|
||||
When I navigate to "Server > Email > Incoming mail configuration" in site administration
|
||||
And I set the field "Mailbox name" to "frogfrogfrogfrog"
|
||||
Then I should see "Maximum of 15 characters"
|
||||
And the "disabled" attribute of "form#adminsettings button[type='submit']" "css_element" should contain "true"
|
||||
And I set the field "Mailbox name" to "frogfrogfrogfro"
|
||||
And I should not see "Maximum of 15 characters"
|
||||
And the "disabled" attribute of "form#adminsettings button[type='submit']" "css_element" should not be set
|
||||
|
@ -871,6 +871,7 @@ sites. If this is not what you wanted then you should make sure you are updating
|
||||
from a STABLE branch of the Moodle code. See Moodle Docs for more details.';
|
||||
$string['maxbytes'] = 'Maximum uploaded file size';
|
||||
$string['maxconsecutiveidentchars'] = 'Consecutive identical characters';
|
||||
$string['maxcharacter'] = '{$a} character maximum';
|
||||
$string['maxsizeperdownloadcoursefile'] = 'Maximum size per file';
|
||||
$string['maxsizeperdownloadcoursefile_desc'] = 'The maximum size of each file when downloading course content. Files exceeding this size will be omitted from the download.';
|
||||
$string['maxeditingtime'] = 'Maximum time to edit posts';
|
||||
|
@ -2447,6 +2447,8 @@ class admin_setting_configtext extends admin_setting {
|
||||
|
||||
/** @var int default field size */
|
||||
public $size;
|
||||
/** @var array List of arbitrary data attributes */
|
||||
protected $datavalues = [];
|
||||
|
||||
/**
|
||||
* Config text constructor
|
||||
@ -2530,11 +2532,24 @@ class admin_setting_configtext extends admin_setting {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set arbitrary data attributes for template.
|
||||
*
|
||||
* @param string $key Attribute key for template.
|
||||
* @param string $value Attribute value for template.
|
||||
*/
|
||||
public function set_data_attribute(string $key, string $value): void {
|
||||
$this->datavalues[] = [
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an XHTML string for the setting
|
||||
* @return string Returns an XHTML string
|
||||
*/
|
||||
public function output_html($data, $query='') {
|
||||
public function output_html($data, $query = '') {
|
||||
global $OUTPUT;
|
||||
|
||||
$default = $this->get_defaultsetting();
|
||||
@ -2545,6 +2560,8 @@ class admin_setting_configtext extends admin_setting {
|
||||
'value' => $data,
|
||||
'forceltr' => $this->get_force_ltr(),
|
||||
'readonly' => $this->is_readonly(),
|
||||
'data' => $this->datavalues,
|
||||
'maxcharacter' => array_key_exists('validation-max-length', $this->datavalues),
|
||||
];
|
||||
$element = $OUTPUT->render_from_template('core_admin/setting_configtext', $context);
|
||||
|
||||
@ -2578,6 +2595,7 @@ class admin_setting_configtext_with_maxlength extends admin_setting_configtext {
|
||||
public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW,
|
||||
$size=null, $maxlength = 0) {
|
||||
$this->maxlength = $maxlength;
|
||||
$this->set_data_attribute('validation-max-length', $maxlength);
|
||||
parent::__construct($name, $visiblename, $description, $defaultsetting, $paramtype, $size);
|
||||
}
|
||||
|
||||
@ -2604,6 +2622,20 @@ class admin_setting_configtext_with_maxlength extends admin_setting_configtext {
|
||||
return $parentvalidation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an XHTML string for the setting.
|
||||
*
|
||||
* @param string $data data.
|
||||
* @param string $query query statement.
|
||||
* @return string Returns an XHTML string
|
||||
*/
|
||||
public function output_html($data, $query = ''): string {
|
||||
global $PAGE;
|
||||
$PAGE->requires->js_call_amd('core_form/configtext_maxlength', 'init');
|
||||
|
||||
return parent::output_html($data, $query);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
3
lib/form/amd/build/configtext_maxlength.min.js
vendored
Normal file
3
lib/form/amd/build/configtext_maxlength.min.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
define("core_form/configtext_maxlength",["exports","core/str","core/templates","core/notification","core/prefetch"],(function(_exports,_str,_templates,_notification,_prefetch){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_templates=_interopRequireDefault(_templates),_notification=_interopRequireDefault(_notification);let registered=!1;_exports.init=()=>{registered||((0,_prefetch.prefetchStrings)("core",["maximumchars"]),(0,_prefetch.prefetchTemplates)(["core_form/setting_validation_failure"]),registered=!0,document.addEventListener("input",(e=>{const maxLengthField=e.target.closest("[data-validation-max-length]");if(maxLengthField)if(maxLengthField.value.length>maxLengthField.dataset.validationMaxLength)maxLengthField.form.addEventListener("submit",submissionCheck),(0,_str.get_string)("maximumchars","core",maxLengthField.dataset.validationMaxLength).then((errorMessage=>_templates.default.renderForPromise("core_form/setting_validation_failure",{fieldid:maxLengthField.id,message:errorMessage}))).then((errorTemplate=>{if(!maxLengthField.dataset.validationFailureId){const formWrapper=maxLengthField.closest(".form-text");_templates.default.prependNodeContents(formWrapper,errorTemplate.html,errorTemplate.js),maxLengthField.dataset.validationFailureId="maxlength_error_".concat(maxLengthField.id),updateSubmitButton()}})).then((()=>{maxLengthField.setAttribute("aria-invalid",!0);const errorField=document.getElementById(maxLengthField.dataset.validationFailureId);errorField&&errorField.setAttribute("aria-describedby",maxLengthField.id)})).catch(_notification.default.exception);else{const validationMessage=document.getElementById(maxLengthField.dataset.validationFailureId);validationMessage&&(validationMessage.parentElement.remove(),delete maxLengthField.dataset.validationFailureId,maxLengthField.removeAttribute("aria-invalid"),updateSubmitButton())}})))};const submissionCheck=e=>{const maxLengthFields=e.target.querySelectorAll("[data-validation-max-length]");Array.from(maxLengthFields).some((maxLengthField=>maxLengthField.value.length>maxLengthField.dataset.validationMaxLength&&(e.preventDefault(),maxLengthField.focus(),!0)))},updateSubmitButton=()=>{const shouldDisable=document.querySelector("form#adminsettings .error");document.querySelector('form#adminsettings button[type="submit"]').disabled=!!shouldDisable}}));
|
||||
|
||||
//# sourceMappingURL=configtext_maxlength.min.js.map
|
1
lib/form/amd/build/configtext_maxlength.min.js.map
Normal file
1
lib/form/amd/build/configtext_maxlength.min.js.map
Normal file
File diff suppressed because one or more lines are too long
121
lib/form/amd/src/configtext_maxlength.js
Normal file
121
lib/form/amd/src/configtext_maxlength.js
Normal file
@ -0,0 +1,121 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Validation for configtext_maxlength.
|
||||
*
|
||||
* @module core_form/configtext-maxlength
|
||||
* @copyright 2021 The Open University
|
||||
*/
|
||||
import {get_string as getString} from 'core/str';
|
||||
import Templates from 'core/templates';
|
||||
import Notification from 'core/notification';
|
||||
import {prefetchStrings, prefetchTemplates} from 'core/prefetch';
|
||||
|
||||
let registered = false;
|
||||
|
||||
/**
|
||||
* Initialisation function.
|
||||
*/
|
||||
export const init = () => {
|
||||
if (registered) {
|
||||
return;
|
||||
}
|
||||
prefetchStrings('core', [
|
||||
'maximumchars',
|
||||
]);
|
||||
|
||||
prefetchTemplates([
|
||||
'core_form/setting_validation_failure',
|
||||
]);
|
||||
|
||||
registered = true;
|
||||
|
||||
document.addEventListener('input', e => {
|
||||
const maxLengthField = e.target.closest('[data-validation-max-length]');
|
||||
if (!maxLengthField) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (maxLengthField.value.length > maxLengthField.dataset.validationMaxLength) {
|
||||
// Disable the form for this field.
|
||||
maxLengthField.form.addEventListener('submit', submissionCheck);
|
||||
// Display an error.
|
||||
getString('maximumchars', 'core', maxLengthField.dataset.validationMaxLength)
|
||||
.then(errorMessage => {
|
||||
return Templates.renderForPromise('core_form/setting_validation_failure', {
|
||||
fieldid: maxLengthField.id,
|
||||
message: errorMessage,
|
||||
});
|
||||
})
|
||||
.then(errorTemplate => {
|
||||
if (!maxLengthField.dataset.validationFailureId) {
|
||||
const formWrapper = maxLengthField.closest('.form-text');
|
||||
Templates.prependNodeContents(formWrapper, errorTemplate.html, errorTemplate.js);
|
||||
maxLengthField.dataset.validationFailureId = `maxlength_error_${maxLengthField.id}`;
|
||||
// Disable submit button when the message is displayed.
|
||||
updateSubmitButton();
|
||||
}
|
||||
return;
|
||||
})
|
||||
.then(() => {
|
||||
maxLengthField.setAttribute('aria-invalid', true);
|
||||
const errorField = document.getElementById(maxLengthField.dataset.validationFailureId);
|
||||
if (errorField) {
|
||||
errorField.setAttribute('aria-describedby', maxLengthField.id);
|
||||
}
|
||||
return;
|
||||
})
|
||||
.catch(Notification.exception);
|
||||
} else {
|
||||
// Remove the old message.
|
||||
const validationMessage = document.getElementById(maxLengthField.dataset.validationFailureId);
|
||||
if (validationMessage) {
|
||||
validationMessage.parentElement.remove();
|
||||
delete maxLengthField.dataset.validationFailureId;
|
||||
maxLengthField.removeAttribute('aria-invalid');
|
||||
// Enable submit button when the message was removed.
|
||||
updateSubmitButton();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle form submission.
|
||||
*
|
||||
* @param {Event} e The event.
|
||||
*/
|
||||
const submissionCheck = e => {
|
||||
const maxLengthFields = e.target.querySelectorAll('[data-validation-max-length]');
|
||||
const maxLengthFieldsArray = Array.from(maxLengthFields);
|
||||
maxLengthFieldsArray.some(maxLengthField => {
|
||||
// Focus on the first validation failure.
|
||||
if (maxLengthField.value.length > maxLengthField.dataset.validationMaxLength) {
|
||||
e.preventDefault();
|
||||
maxLengthField.focus();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Update submit button.
|
||||
*/
|
||||
const updateSubmitButton = () => {
|
||||
const shouldDisable = document.querySelector('form#adminsettings .error');
|
||||
document.querySelector('form#adminsettings button[type="submit"]').disabled = !!shouldDisable;
|
||||
};
|
36
lib/form/templates/setting_validation_failure.mustache
Normal file
36
lib/form/templates/setting_validation_failure.mustache
Normal file
@ -0,0 +1,36 @@
|
||||
{{!
|
||||
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/>.
|
||||
}}
|
||||
{{!
|
||||
@template core_form/setting_validation_failure
|
||||
Error displayed when field fails validation (longer than max length).
|
||||
|
||||
Context variables required for this template:
|
||||
* fieldid - element field id
|
||||
* message - error message
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"fieldid": "test0",
|
||||
"message": "test message"
|
||||
}
|
||||
}}
|
||||
{{!
|
||||
Setting error template for configtext_maxlength.
|
||||
}}
|
||||
<div>
|
||||
<span class="error" id="maxlength_error_{{fieldid}}">{{message}}</span>
|
||||
</div>
|
Loading…
x
Reference in New Issue
Block a user