mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 12:32:08 +02:00
MDL-72928 login: Update styling and functionality
This commit is contained in:
parent
5897242361
commit
ecb92c7ed9
@ -0,0 +1,134 @@
|
||||
|
||||
---
|
||||
layout: docs
|
||||
title: "HTML Modals"
|
||||
description: "A reusable handled modal component"
|
||||
date: 2021-12-09T14:48:00+08:00
|
||||
draft: false
|
||||
tags:
|
||||
- MDL-71963
|
||||
- MDL-72928
|
||||
- "4.0"
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
The core/utility module allows different modals to be displayed automatically when interacting with the page.
|
||||
|
||||
Modals are configured using a set of specific data-attributes.
|
||||
|
||||
## Source files
|
||||
|
||||
* `lib/amd/src/utility.js` ({{< jsdoc module="core/utility" >}})
|
||||
* `lib/templates/modal.mustache`
|
||||
|
||||
## Usage
|
||||
The confirmation AMD module is loaded automatically, so the only thing you need to do is to add some specific data attributes
|
||||
to the target element.
|
||||
|
||||
To display a confirmation modal.
|
||||
{{< highlight html >}}
|
||||
<button type="button" class="btn btn-primary" data-modal="confirmation" data-modal-title-str='["delete", "core"]'
|
||||
data-modal-content-str='["areyousure"]' data-modal-yes-button-str='["delete", "core"]'>Show confirmation modal</button>
|
||||
{{< /highlight >}}
|
||||
|
||||
To display an alert modal.
|
||||
{{< highlight html >}}
|
||||
<button type="button" class="btn btn-primary" data-modal="alert" data-modal-title-str='["cookiesenabled", "core"]'
|
||||
data-modal-content-str='["cookiesenabled_help_html", "core"]'>Show alert modal</button>
|
||||
{{< /highlight >}}
|
||||
|
||||
You can also use it on PHP, you just need to set the attributes parameter to any moodle output component that takes attributes:
|
||||
{{< php >}}
|
||||
echo $OUTPUT->single_button('#', get_string('delete'), 'get', [
|
||||
'data-modal' => 'modal',
|
||||
'data-modal-title-str' => json_encode(['delete', 'core']),
|
||||
'data-modal-content-str' => json_encode(['areyousure']),
|
||||
'data-modal-yes-button-str' => json_encode(['delete', 'core'])
|
||||
]);
|
||||
{{< / php >}}
|
||||
|
||||
## Attributes
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 250px;">Data attribute</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>data-modal</td>
|
||||
<td>One of either "confirmation", or "alert".</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>data-modal-title-str</td>
|
||||
<td>The modal title language string identifier, must be provided in JSON encoded format.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>data-modal-content-str</td>
|
||||
<td>The modal content or content language string identifier, must be provided in JSON encoded format.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>data-modal-yes-button-str</td>
|
||||
<td>
|
||||
The language string identifier for the "Yes" button, must be provided in JSON encoded format.
|
||||
Confirmation modals only.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>data-modal-toast</td>
|
||||
<td>
|
||||
If set to "true" it will display a modal toast in the end.
|
||||
Confirmation modals only.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>data-modal-toast-confirmation-str</td>
|
||||
<td>
|
||||
The confirmation toast language string identifier, must be provided in JSON encoded format.
|
||||
Confirmation modals only.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>data-modal-destination</td>
|
||||
<td>
|
||||
An url to redirect the user to.
|
||||
Confirmation modals only.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Alert modal
|
||||
|
||||
{{< example >}}
|
||||
<button type="button" class="btn btn-primary" data-modal="alert" data-modal-title-str='["cookiesenabled", "core"]'
|
||||
data-modal-content-str='["cookiesenabled_help_html", "core"]'>Show alert modal</button>
|
||||
{{< /example >}}
|
||||
|
||||
### Basic confirmation modal
|
||||
|
||||
{{< example >}}
|
||||
<button type="button" class="btn btn-primary" data-modal="confirmation" data-modal-title-str='["delete", "core"]'
|
||||
data-modal-content-str='["areyousure"]' data-modal-yes-button-str='["delete", "core"]'>Show confirmation modal</button>
|
||||
{{< /example >}}
|
||||
|
||||
### Confirmation modal with a toast
|
||||
|
||||
{{< example >}}
|
||||
<button type="button" class="btn btn-primary" data-modal="confirmation" data-modal-title-str='["delete", "core"]'
|
||||
data-modal-content-str='["areyousure"]' data-modal-yes-button-str='["delete", "core"]' data-modal-toast="true"
|
||||
data-modal-toast-confirmation-str='["deleteblockinprogress", "block", "Online users"]'>Show confirmation modal</button>
|
||||
{{< /example >}}
|
||||
|
||||
### Confirmation modal with redirect
|
||||
|
||||
{{< example >}}
|
||||
<button type="button" class="btn btn-primary" data-modal="confirmation" data-modal-title-str='["delete", "core"]'
|
||||
data-modal-content-str='["areyousure"]' data-modal-yes-button-str='["delete", "core"]'
|
||||
data-modal-destination="http://moodle.com">Show confirmation modal</button>
|
||||
{{< /example >}}
|
@ -24,27 +24,3 @@ Feature: Test the 'remember username' feature works.
|
||||
And I click on "Log in" "link" in the ".logininfo" "css_element"
|
||||
Then the field "username" matches value "teacher1"
|
||||
And the field "Remember username" matches value "1"
|
||||
|
||||
# Given the user has logged in before and selected 'Remember username', when they log in again and unset 'Remember username', then
|
||||
# their username should be forgotten for future log in attempts.
|
||||
Scenario: Check that 'remember username' unsetting works without javascript for teachers.
|
||||
# Log in the first time and check the 'remember username' box.
|
||||
Given I am on homepage
|
||||
And I click on "Log in" "link" in the ".logininfo" "css_element"
|
||||
And I set the field "Username" to "teacher1"
|
||||
And I set the field "Password" to "teacher1"
|
||||
And I set the field "Remember username" to "1"
|
||||
And I press "Log in"
|
||||
And I log out
|
||||
# Log in again, unsetting the 'remember username' field.
|
||||
When I am on homepage
|
||||
And I click on "Log in" "link" in the ".logininfo" "css_element"
|
||||
And I set the field "Password" to "teacher1"
|
||||
And I set the field "Remember username" to "0"
|
||||
And I press "Log in"
|
||||
And I log out
|
||||
# Check username has been forgotten.
|
||||
Then I am on homepage
|
||||
And I click on "Log in" "link" in the ".logininfo" "css_element"
|
||||
Then the field "username" matches value ""
|
||||
And the field "Remember username" matches value "0"
|
||||
|
@ -299,10 +299,16 @@ $string['cookiesenabled_help'] = 'Two cookies are used on this site:
|
||||
|
||||
The essential one is the session cookie, usually called MoodleSession. You must allow this cookie in your browser to provide continuity and to remain logged in when browsing the site. When you log out or close the browser, this cookie is destroyed (in your browser and on the server).
|
||||
|
||||
The other cookie is purely for convenience, usually called MOODLEID or similar. It just remembers your username in the browser. This means that when you return to this site, the username field on the login page is already filled in for you. It is safe to refuse this cookie - you will just have to retype your username each time you log in.';
|
||||
$string['cookiesenabled_help_html'] = 'Two cookies are used on this site:<br/><br/>
|
||||
|
||||
The essential one is the session cookie, usually called MoodleSession. You must allow this cookie in your browser to provide continuity and to remain logged in when browsing the site. When you log out or close the browser, this cookie is destroyed (in your browser and on the server).<br/><br/>
|
||||
|
||||
The other cookie is purely for convenience, usually called MOODLEID or similar. It just remembers your username in the browser. This means that when you return to this site, the username field on the login page is already filled in for you. It is safe to refuse this cookie - you will just have to retype your username each time you log in.';
|
||||
$string['cookiesenabledonlysession'] = 'Cookies must be enabled in your browser';
|
||||
$string['cookiesenabledonlysession_help'] = 'This site uses one session cookie, usually called MoodleSession. You must allow this cookie in your browser to provide continuity and to remain logged in when browsing the site. When you log out or close the browser, this cookie is destroyed (in your browser and on the server).';
|
||||
$string['cookiesnotenabled'] = 'Unfortunately, cookies are currently not enabled in your browser';
|
||||
$string['cookiesnotice'] = 'Cookies notice';
|
||||
$string['copy'] = 'copy';
|
||||
$string['copyasnoun'] = 'copy';
|
||||
$string['copycourse'] = 'Copy course';
|
||||
@ -2250,7 +2256,7 @@ $string['userlist'] = 'User list';
|
||||
$string['usermenu'] = 'User menu';
|
||||
$string['usermenugoback'] = 'Go back to user menu';
|
||||
$string['username'] = 'Username';
|
||||
$string['usernameemail'] = 'Username / email';
|
||||
$string['usernameemail'] = 'Username or email';
|
||||
$string['usernameemailmatch'] = 'The username and email address do not relate to the same user';
|
||||
$string['usernameexists'] = 'This username already exists, choose another';
|
||||
$string['usernamelowercase'] = 'Only lowercase letters allowed';
|
||||
|
2
lib/amd/build/confirm.min.js
vendored
2
lib/amd/build/confirm.min.js
vendored
@ -1,2 +0,0 @@
|
||||
function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core/confirm",["core/notification","core/str","core/toast"],function(a,b,c){"use strict";b=e(b);function d(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;d=function(){return a};return a}function e(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=d();if(b&&b.has(a)){return b.get(a)}var c={},e=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var f in a){if(Object.prototype.hasOwnProperty.call(a,f)){var g=e?Object.getOwnPropertyDescriptor(a,f):null;if(g&&(g.get||g.set)){Object.defineProperty(c,f,g)}else{c[f]=a[f]}}}c.default=a;if(b){b.set(a,c)}return c}var f=!1,g=function(a,c){if(a["confirmation".concat(c,"Str")]){return b.get_string.apply(null,JSON.parse(a["confirmation".concat(c,"Str")]))}return Promise.resolve(a["confirmation".concat(c)])},h=function(){document.addEventListener("click",function(b){var d=b.target.closest("[data-confirmation=\"modal\"]");if(d){b.preventDefault();(0,a.saveCancelPromise)(g(d.dataset,"Title"),g(d.dataset,"Question"),g(d.dataset,"YesButton")).then(function(){if("true"===d.dataset.confirmationToast){var b=g(d.dataset,"ToastConfirmation");if("string"==typeof b){(0,c.add)(b)}else{b.then(function(a){return(0,c.add)(a)}).catch(function(b){return(0,a.exception)(b)})}}window.location.href=d.dataset.confirmationDestination}).catch(function(){})}})};if(!f){h();f=!0}});
|
||||
//# sourceMappingURL=confirm.min.js.map
|
File diff suppressed because one or more lines are too long
2
lib/amd/build/utility.min.js
vendored
Normal file
2
lib/amd/build/utility.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core/utility",["core/str","core/pending","core/toast","core/notification"],function(a,b,c,d){"use strict";a=f(a);b=function(a){return a&&a.__esModule?a:{default:a}}(b);var i="undefined"!=typeof window?window:"undefined"!=typeof self?self:"undefined"!=typeof global?global:{};function e(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;e=function(){return a};return a}function f(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=e();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var f in a){if(Object.prototype.hasOwnProperty.call(a,f)){var g=d?Object.getOwnPropertyDescriptor(a,f):null;if(g&&(g.get||g.set)){Object.defineProperty(c,f,g)}else{c[f]=a[f]}}}c.default=a;if(b){b.set(a,c)}return c}function g(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function h(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var i=a.apply(b,c);function f(a){g(i,d,e,f,h,"next",a)}function h(a){g(i,d,e,f,h,"throw",a)}f(void 0)})}}var j=!1,k=function(b,c,d){if(b["".concat(c).concat(d,"Str")]){return a.get_string.apply(null,JSON.parse(b["".concat(c).concat(d,"Str")]))}return Promise.resolve(b["".concat(c).concat(d)])},l=function(a,b){return(0,d.saveCancelPromise)(k(a.dataset,b,"Title"),k(a.dataset,b,"Content"),k(a.dataset,b,"YesButton")).then(function(){if("true"===a.dataset["".concat(b,"Toast")]){var e=k(a.dataset,b,"ToastConfirmation");if("string"==typeof e){(0,c.add)(e)}else{e.then(function(a){return(0,c.add)(a)}).catch(function(a){return(0,d.exception)(a)})}}window.location.href=a.dataset["".concat(b,"Destination")]}).catch(function(){})},m=function(){var a=h(regeneratorRuntime.mark(function a(c,d){var e,f;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:e=new b.default("core/confirm:alert");a.next=3;return"function"==typeof i.define&&i.define.amd?new Promise(function(a,b){i.require(["core/modal_factory"],a,b)}):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&i.require&&"component"===i.require.loader?Promise.resolve(require(("core/modal_factory"))):Promise.resolve(i["core/modal_factory"]);case 3:f=a.sent;return a.abrupt("return",f.create({type:f.types.ALERT,title:c,body:d,removeOnClose:!0}).then(function(a){a.show();e.resolve();return a}));case 5:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}(),n=function(){document.addEventListener("click",function(a){var b=a.target.closest("[data-confirmation=\"modal\"]");if(b){a.preventDefault();l(b,"confirmation")}var c=a.target.closest("[data-modal=\"confirmation\"]");if(c){a.preventDefault();l(c,"modal")}var d=a.target.closest("[data-modal=\"alert\"]");if(d){a.preventDefault();m(k(d.dataset,"modal","Title"),k(d.dataset,"modal","Content"))}})};if(!j){n();j=!0}});
|
||||
//# sourceMappingURL=utility.min.js.map
|
1
lib/amd/build/utility.min.js.map
Normal file
1
lib/amd/build/utility.min.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -1,106 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Javascript events for the `core_confirm` modal.
|
||||
*
|
||||
* @module core/confirm
|
||||
* @copyright 2021 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @since 4.0
|
||||
*
|
||||
* @example <caption>Calling the confirmation modal to delete a block</caption>
|
||||
*
|
||||
* // The following is an example of how to use this module via an indirect PHP call with a button.
|
||||
*
|
||||
* $controls[] = new action_menu_link_secondary(
|
||||
* $deleteactionurl,
|
||||
* new pix_icon('t/delete', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
|
||||
* $str,
|
||||
* [
|
||||
* 'class' => 'editing_delete',
|
||||
* 'data-confirmation' => 'modal', // Needed so this module will pick it up in the click handler.
|
||||
* 'data-confirmation-title-str' => json_encode(['deletecheck_modal', 'block']),
|
||||
* 'data-confirmation-question-str' => json_encode(['deleteblockcheck', 'block', $blocktitle]),
|
||||
* 'data-confirmation-yes-button-str' => json_encode(['delete', 'core']),
|
||||
* 'data-confirmation-toast' => 'true', // Can be set to inform the user that their action was a success.
|
||||
* 'data-confirmation-toast-confirmation-str' => json_encode(['deleteblockinprogress', 'block', $blocktitle]),
|
||||
* 'data-confirmation-destination' => $deleteconfirmationurl->out(false), // Where do you want to direct the user?
|
||||
* ]
|
||||
* );
|
||||
*/
|
||||
|
||||
import {saveCancelPromise, exception} from 'core/notification';
|
||||
import * as Str from 'core/str';
|
||||
import {add as addToast} from 'core/toast';
|
||||
|
||||
// We want to ensure that we only initialize the listeners only once.
|
||||
let registered = false;
|
||||
|
||||
/**
|
||||
* Either fetch the string or return it from the dom node.
|
||||
*
|
||||
* @method getConfirmationString
|
||||
* @private
|
||||
* @param {HTMLElement} dataset The page element to fetch dataset items in
|
||||
* @param {String} field The dataset field name to fetch the contents of
|
||||
* @return {Promise}
|
||||
*
|
||||
*/
|
||||
const getConfirmationString = (dataset, field) => {
|
||||
if (dataset[`confirmation${field}Str`]) {
|
||||
return Str.get_string.apply(null, JSON.parse(dataset[`confirmation${field}Str`]));
|
||||
}
|
||||
return Promise.resolve(dataset[`confirmation${field}`]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set up the listeners for the confirmation modal widget within the page.
|
||||
*
|
||||
* @method registerConfirmationListeners
|
||||
* @private
|
||||
*/
|
||||
const registerConfirmationListeners = () => {
|
||||
document.addEventListener('click', e => {
|
||||
const confirmRequest = e.target.closest('[data-confirmation="modal"]');
|
||||
if (confirmRequest) {
|
||||
e.preventDefault();
|
||||
saveCancelPromise(
|
||||
getConfirmationString(confirmRequest.dataset, 'Title'),
|
||||
getConfirmationString(confirmRequest.dataset, 'Question'),
|
||||
getConfirmationString(confirmRequest.dataset, 'YesButton'),
|
||||
)
|
||||
.then(() => {
|
||||
if (confirmRequest.dataset.confirmationToast === 'true') {
|
||||
const stringForToast = getConfirmationString(confirmRequest.dataset, 'ToastConfirmation');
|
||||
if (typeof stringForToast === "string") {
|
||||
addToast(stringForToast);
|
||||
} else {
|
||||
stringForToast.then(str => addToast(str)).catch(e => exception(e));
|
||||
}
|
||||
}
|
||||
window.location.href = confirmRequest.dataset.confirmationDestination;
|
||||
return;
|
||||
}).catch(() => {
|
||||
return;
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (!registered) {
|
||||
registerConfirmationListeners();
|
||||
registered = true;
|
||||
}
|
165
lib/amd/src/utility.js
Normal file
165
lib/amd/src/utility.js
Normal file
@ -0,0 +1,165 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Javascript handling for HTML attributes. This module gets autoloaded on page load.
|
||||
*
|
||||
* With the appropriate HTML attributes, various functionalities defined in this module can be used such as a displaying
|
||||
* an alert or a confirmation modal, etc.
|
||||
*
|
||||
* @module core/utility
|
||||
* @copyright 2021 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @since 4.0
|
||||
*
|
||||
* @example <caption>Calling the confirmation modal to delete a block</caption>
|
||||
*
|
||||
* // The following is an example of how to use this module via an indirect PHP call with a button.
|
||||
*
|
||||
* $controls[] = new action_menu_link_secondary(
|
||||
* $deleteactionurl,
|
||||
* new pix_icon('t/delete', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
|
||||
* $str,
|
||||
* [
|
||||
* 'class' => 'editing_delete',
|
||||
* 'data-modal' => 'confirmation', // Needed so this module will pick it up in the click handler.
|
||||
* 'data-modal-title-str' => json_encode(['deletecheck_modal', 'block']),
|
||||
* 'data-modal-content-str' => json_encode(['deleteblockcheck', 'block', $blocktitle]),
|
||||
* 'data-modal-yes-button-str' => json_encode(['delete', 'core']),
|
||||
* 'data-modal-toast' => 'true', // Can be set to inform the user that their action was a success.
|
||||
* 'data-modal-toast-confirmation-str' => json_encode(['deleteblockinprogress', 'block', $blocktitle]),
|
||||
* 'data-modal-destination' => $deleteconfirmationurl->out(false), // Where do you want to direct the user?
|
||||
* ]
|
||||
* );
|
||||
*/
|
||||
|
||||
import * as Str from 'core/str';
|
||||
import Pending from 'core/pending';
|
||||
import {add as addToast} from 'core/toast';
|
||||
import {saveCancelPromise, exception} from 'core/notification';
|
||||
|
||||
// We want to ensure that we only initialize the listeners only once.
|
||||
let registered = false;
|
||||
|
||||
/**
|
||||
* Either fetch the string or return it from the dom node.
|
||||
*
|
||||
* @method getConfirmationString
|
||||
* @private
|
||||
* @param {HTMLElement} dataset The page element to fetch dataset items in
|
||||
* @param {String} type The type of string to fetch
|
||||
* @param {String} field The dataset field name to fetch the contents of
|
||||
* @return {Promise}
|
||||
*
|
||||
*/
|
||||
const getModalString = (dataset, type, field) => {
|
||||
if (dataset[`${type}${field}Str`]) {
|
||||
return Str.get_string.apply(null, JSON.parse(dataset[`${type}${field}Str`]));
|
||||
}
|
||||
return Promise.resolve(dataset[`${type}${field}`]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Display a save/cancel confirmation.
|
||||
*
|
||||
* @private
|
||||
* @param {HTMLElement} source The title of the confirmation
|
||||
* @param {String} type The content of the confirmation
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const displayConfirmation = (source, type) => {
|
||||
return saveCancelPromise(
|
||||
getModalString(source.dataset, type, 'Title'),
|
||||
getModalString(source.dataset, type, 'Content'),
|
||||
getModalString(source.dataset, type, 'YesButton'),
|
||||
)
|
||||
.then(() => {
|
||||
if (source.dataset[`${type}Toast`] === 'true') {
|
||||
const stringForToast = getModalString(source.dataset, type, 'ToastConfirmation');
|
||||
if (typeof stringForToast === "string") {
|
||||
addToast(stringForToast);
|
||||
} else {
|
||||
stringForToast.then(str => addToast(str)).catch(e => exception(e));
|
||||
}
|
||||
}
|
||||
window.location.href = source.dataset[`${type}Destination`];
|
||||
return;
|
||||
}).catch(() => {
|
||||
return;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Display an alert and return the promise from it.
|
||||
*
|
||||
* @private
|
||||
* @param {String} title The title of the alert
|
||||
* @param {String} content The content of the alert
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const displayAlert = async(title, content) => {
|
||||
const pendingPromise = new Pending('core/confirm:alert');
|
||||
|
||||
const ModalFactory = await import('core/modal_factory');
|
||||
|
||||
return ModalFactory.create({
|
||||
type: ModalFactory.types.ALERT,
|
||||
title: title,
|
||||
body: content,
|
||||
removeOnClose: true,
|
||||
})
|
||||
.then(function(modal) {
|
||||
modal.show();
|
||||
pendingPromise.resolve();
|
||||
|
||||
return modal;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Set up the listeners for the confirmation modal widget within the page.
|
||||
*
|
||||
* @method registerConfirmationListeners
|
||||
* @private
|
||||
*/
|
||||
const registerConfirmationListeners = () => {
|
||||
document.addEventListener('click', e => {
|
||||
const confirmRequest = e.target.closest('[data-confirmation="modal"]');
|
||||
if (confirmRequest) {
|
||||
e.preventDefault();
|
||||
displayConfirmation(confirmRequest, 'confirmation');
|
||||
}
|
||||
|
||||
const modalConfirmation = e.target.closest('[data-modal="confirmation"]');
|
||||
if (modalConfirmation) {
|
||||
e.preventDefault();
|
||||
displayConfirmation(modalConfirmation, 'modal');
|
||||
}
|
||||
|
||||
const alertRequest = e.target.closest('[data-modal="alert"]');
|
||||
if (alertRequest) {
|
||||
e.preventDefault();
|
||||
displayAlert(
|
||||
getModalString(alertRequest.dataset, 'modal', 'Title'),
|
||||
getModalString(alertRequest.dataset, 'modal', 'Content'),
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (!registered) {
|
||||
registerConfirmationListeners();
|
||||
registered = true;
|
||||
}
|
@ -1416,13 +1416,13 @@ class block_manager {
|
||||
$str,
|
||||
[
|
||||
'class' => 'editing_delete',
|
||||
'data-confirmation' => 'modal',
|
||||
'data-confirmation-title-str' => json_encode(['deletecheck_modal', 'block']),
|
||||
'data-confirmation-question-str' => json_encode(['deleteblockcheck', 'block', $blocktitle]),
|
||||
'data-confirmation-yes-button-str' => json_encode(['delete', 'core']),
|
||||
'data-confirmation-toast' => 'true',
|
||||
'data-confirmation-toast-confirmation-str' => json_encode(['deleteblockinprogress', 'block', $blocktitle]),
|
||||
'data-confirmation-destination' => $deleteconfirmationurl->out(false),
|
||||
'data-modal' => 'confirmation',
|
||||
'data-modal-title-str' => json_encode(['deletecheck_modal', 'block']),
|
||||
'data-modal-content-str' => json_encode(['deleteblockcheck', 'block', $blocktitle]),
|
||||
'data-modal-yes-button-str' => json_encode(['delete', 'core']),
|
||||
'data-modal-toast' => 'true',
|
||||
'data-modal-toast-confirmation-str' => json_encode(['deleteblockinprogress', 'block', $blocktitle]),
|
||||
'data-modal-destination' => $deleteconfirmationurl->out(false),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -4753,12 +4753,6 @@ EOD;
|
||||
|
||||
$context = $form->export_for_template($this);
|
||||
|
||||
// Override because rendering is not supported in template yet.
|
||||
if ($CFG->rememberusername == 0) {
|
||||
$context->cookieshelpiconformatted = $this->help_icon('cookiesenabledonlysession');
|
||||
} else {
|
||||
$context->cookieshelpiconformatted = $this->help_icon('cookiesenabled');
|
||||
}
|
||||
$context->errorformatted = $this->error_text($context->error);
|
||||
$url = $this->get_logo_url();
|
||||
if ($url) {
|
||||
|
@ -1669,7 +1669,7 @@ EOF;
|
||||
$this->js_call_amd('core/log', 'setConfig', array($logconfig));
|
||||
// Add any global JS that needs to run on all pages.
|
||||
$this->js_call_amd('core/page_global', 'init');
|
||||
$this->js_call_amd('core/confirm');
|
||||
$this->js_call_amd('core/utility');
|
||||
|
||||
// Call amd init functions.
|
||||
$output .= $this->get_amd_footercode();
|
||||
|
@ -35,7 +35,6 @@
|
||||
* loginurl - Login url,
|
||||
* rememberusername - Remeber username?,
|
||||
* signupurl - Signup url,
|
||||
* cookieshelpiconformatted - Formatted html of cookies help icon,
|
||||
* errorformatted - Formatted error,
|
||||
* logourl - Flag, logo url,
|
||||
* sitename - Name of site.,
|
||||
@ -97,11 +96,6 @@
|
||||
}}
|
||||
|
||||
<div class="loginform">
|
||||
{{#languagemenu}}
|
||||
<div class="login-languagemenu">
|
||||
{{>core/action_menu}}
|
||||
</div>
|
||||
{{/languagemenu}}
|
||||
{{#logourl}}
|
||||
<div id="loginlogo" class="login-logo">
|
||||
<img id="logoimage" src="{{logourl}}" class="img-fluid" alt="{{sitename}}"/>
|
||||
@ -135,7 +129,7 @@
|
||||
{{/canloginbyemail}}
|
||||
</label>
|
||||
<input type="text" name="username" id="username" {{!
|
||||
!}}class="form-control" {{!
|
||||
!}}class="form-control form-control-lg" {{!
|
||||
!}}value="{{username}}" {{!
|
||||
!}}placeholder="{{^canloginbyemail}}{{#cleanstr}}username{{/cleanstr}}{{/canloginbyemail}}{{!
|
||||
!}}{{#canloginbyemail}}{{#cleanstr}}usernameemail{{/cleanstr}}{{/canloginbyemail}}" {{!
|
||||
@ -144,24 +138,15 @@
|
||||
<div class="login-form-password form-group">
|
||||
<label for="password" class="sr-only">{{#str}} password {{/str}}</label>
|
||||
<input type="password" name="password" id="password" value="" {{!
|
||||
!}}class="form-control" {{!
|
||||
!}}class="form-control form-control-lg" {{!
|
||||
!}}placeholder="{{#cleanstr}}password{{/cleanstr}}" {{!
|
||||
!}}autocomplete="current-password">
|
||||
</div>
|
||||
{{#rememberusername}}
|
||||
<div class="login-form-rememberusername form-group">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" name="rememberusername" id="rememberusername" class="custom-control-input" value="1"
|
||||
{{#username}}checked{{/username}} />
|
||||
<label class="custom-control-label" for="rememberusername">{{#str}} rememberusername, admin {{/str}}</label>
|
||||
</div>
|
||||
</div>
|
||||
{{/rememberusername}}
|
||||
<div class="login-form-submit form-group">
|
||||
<button class="btn btn-primary btn-lg" type="submit" id="loginbtn">{{#str}}login{{/str}}</button>
|
||||
</div>
|
||||
<div class="login-form-forgotpassword form-group">
|
||||
<a href="{{forgotpasswordurl}}">{{#str}}forgotten{{/str}}</a>
|
||||
<a href="{{forgotpasswordurl}}">{{#str}}forgotaccount{{/str}}</a>
|
||||
</div>
|
||||
</form>
|
||||
{{#hasidentityproviders}}
|
||||
@ -169,7 +154,7 @@
|
||||
<div class="login-identityproviders">
|
||||
<h2 class="login-heading">{{#str}} potentialidps, auth {{/str}}</h2>
|
||||
{{#identityproviders}}
|
||||
<a class="btn login-identityprovider-btn" href="{{url}}">
|
||||
<a class="btn login-identityprovider-btn btn-block" href="{{url}}">
|
||||
{{#iconurl}}
|
||||
<img src="{{iconurl}}" alt="" width="24" height="24"/>
|
||||
{{/iconurl}}
|
||||
@ -201,9 +186,18 @@
|
||||
</form>
|
||||
{{/canloginasguest}}
|
||||
<div class="login-divider"></div>
|
||||
<div class="login-cookiemessage">
|
||||
{{#str}} cookiesenabled {{/str}}
|
||||
{{{cookieshelpiconformatted}}}
|
||||
<div class="d-flex">
|
||||
{{#languagemenu}}
|
||||
<div class="login-languagemenu">
|
||||
{{>core/action_menu}}
|
||||
</div>
|
||||
<div class="divider border-left align-self-center mx-3"></div>
|
||||
{{/languagemenu}}
|
||||
<button type="button" class="btn btn-secondary" {{!
|
||||
}} data-modal="alert"{{!
|
||||
}} data-modal-title-str='["cookiesenabled", "core"]' {{!
|
||||
}} data-modal-content-str='["cookiesenabled_help_html", "core"]'{{!
|
||||
}}>{{#str}}cookiesnotice{{/str}}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -35,8 +35,7 @@ $login-identity-provider-btn-border: $border-color !default;
|
||||
margin-bottom: 2rem;
|
||||
.login-languagemenu {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 1rem;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.login-logo {
|
||||
display: flex;
|
||||
@ -61,6 +60,16 @@ $login-identity-provider-btn-border: $border-color !default;
|
||||
border: $border-width solid $login-identity-provider-btn-border;
|
||||
}
|
||||
}
|
||||
.divider {
|
||||
width: $border-width;
|
||||
background-color: $gray-300;
|
||||
height: $font-size-base * 2;
|
||||
}
|
||||
.action-menu-trigger {
|
||||
a {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
|
@ -17626,8 +17626,7 @@ textarea[data-auto-rows] {
|
||||
margin-bottom: 2rem; }
|
||||
.login-container .login-languagemenu {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 1rem; }
|
||||
justify-content: flex-start; }
|
||||
.login-container .login-logo {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@ -17642,6 +17641,12 @@ textarea[data-auto-rows] {
|
||||
font-size: 1.40625rem; }
|
||||
.login-container .login-identityproviders .login-identityprovider-btn {
|
||||
border: 1px solid #dee2e6; }
|
||||
.login-container .divider {
|
||||
width: 1px;
|
||||
background-color: #dee2e6;
|
||||
height: 1.875rem; }
|
||||
.login-container .action-menu-trigger a {
|
||||
margin: 0.5rem 0; }
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.login-container {
|
||||
|
@ -17626,8 +17626,7 @@ textarea[data-auto-rows] {
|
||||
margin-bottom: 2rem; }
|
||||
.login-container .login-languagemenu {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 1rem; }
|
||||
justify-content: flex-start; }
|
||||
.login-container .login-logo {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@ -17642,6 +17641,12 @@ textarea[data-auto-rows] {
|
||||
font-size: 1.40625rem; }
|
||||
.login-container .login-identityproviders .login-identityprovider-btn {
|
||||
border: 1px solid #dee2e6; }
|
||||
.login-container .divider {
|
||||
width: 1px;
|
||||
background-color: #dee2e6;
|
||||
height: 1.875rem; }
|
||||
.login-container .action-menu-trigger a {
|
||||
margin: 0.5rem 0; }
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.login-container {
|
||||
|
Loading…
x
Reference in New Issue
Block a user