Merge branch '96-notify-user-about-incorrect-email-pw-combination' into 'main'
Resolve "Notify user about incorrect email/pw combination" Closes #94 and #96 See merge request stackspin/dashboard!62
This commit is contained in:
commit
696ffba9fe
5 changed files with 303 additions and 323 deletions
|
@ -1,5 +1,12 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
- Fix login welcome message
|
||||||
|
- Clarify "set new password" button (#94)
|
||||||
|
- Show error messages when login fails, for example when a wrong password was
|
||||||
|
entered (#96)
|
||||||
|
|
||||||
## [0.5.1]
|
## [0.5.1]
|
||||||
|
|
||||||
- Fix bug of missing "Monitoring" app access when creating a new user.
|
- Fix bug of missing "Monitoring" app access when creating a new user.
|
||||||
|
|
|
@ -118,7 +118,13 @@ def login():
|
||||||
identity = get_auth()
|
identity = get_auth()
|
||||||
|
|
||||||
if identity:
|
if identity:
|
||||||
return render_template("loggedin.html", api_url=KRATOS_PUBLIC_URL, id=id)
|
if 'name' in identity['traits']:
|
||||||
|
# Add a space in front of the "name" so the template can put it
|
||||||
|
# between "Welcome" and the comma
|
||||||
|
name = " " + identity['traits']['name']
|
||||||
|
else:
|
||||||
|
name = ""
|
||||||
|
return render_template("loggedin.html", api_url=KRATOS_PUBLIC_URL, name=name)
|
||||||
|
|
||||||
flow = request.args.get("flow")
|
flow = request.args.get("flow")
|
||||||
|
|
||||||
|
|
599
backend/web/static/base.js
vendored
599
backend/web/static/base.js
vendored
|
@ -16,257 +16,244 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// Check if an auth flow is configured and redirect to auth page in that
|
// Check if an auth flow is configured and redirect to auth page in that
|
||||||
// case.
|
// case.
|
||||||
function check_flow_auth() {
|
function check_flow_auth() {
|
||||||
var state = Cookies.get('flow_state');
|
var state = Cookies.get('flow_state');
|
||||||
var url = Cookies.get('auth_url');
|
var url = Cookies.get('auth_url');
|
||||||
|
|
||||||
if (state == 'auth') {
|
if (state == 'auth') {
|
||||||
Cookies.set('flow_state','');
|
Cookies.set('flow_state', '');
|
||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if there if the flow is expired, if so, reset the cookie
|
// Check if there if the flow is expired, if so, reset the cookie
|
||||||
function check_flow_expired() {
|
function check_flow_expired() {
|
||||||
var state = Cookies.get('flow_state');
|
var state = Cookies.get('flow_state');
|
||||||
|
|
||||||
if (state == 'flow_expired') {
|
if (state == 'flow_expired') {
|
||||||
Cookies.set('flow_state','');
|
Cookies.set('flow_state', '');
|
||||||
$("#contentFlowExpired").show();
|
$('#contentFlowExpired').show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// The script executed on login flows
|
// The script executed on login flows
|
||||||
function flow_login() {
|
function flow_login() {
|
||||||
|
var flow = $.urlParam('flow');
|
||||||
|
var uri = api_url + 'self-service/login/flows?id=' + flow;
|
||||||
|
|
||||||
var flow = $.urlParam('flow');
|
// Query the Kratos backend to know what fields to render for the
|
||||||
var uri = api_url + 'self-service/login/flows?id=' + flow;
|
// current flow
|
||||||
|
$.ajax({
|
||||||
|
type: 'GET',
|
||||||
|
url: uri,
|
||||||
|
success: function (data) {
|
||||||
|
// Render login form (group: password)
|
||||||
|
var form_html = render_form(data, 'password');
|
||||||
|
$('#contentLogin').html(form_html);
|
||||||
|
|
||||||
// Query the Kratos backend to know what fields to render for the
|
var messages_html = render_messages(data);
|
||||||
// current flow
|
$('#contentMessages').html(messages_html);
|
||||||
$.ajax({
|
},
|
||||||
type: "GET",
|
complete: function (obj) {
|
||||||
url: uri,
|
// If we get a 410, the flow is expired, need to refresh the flow
|
||||||
success: function(data) {
|
if (obj.status == 410) {
|
||||||
|
Cookies.set('flow_state', 'flow_expired');
|
||||||
// Render login form (group: password)
|
// If we call the page without arguments, we get a new flow
|
||||||
var html = render_form(data, 'password');
|
window.location.href = 'login';
|
||||||
$("#contentLogin").html(html);
|
}
|
||||||
|
},
|
||||||
},
|
});
|
||||||
complete: function(obj) {
|
|
||||||
|
|
||||||
// If we get a 410, the flow is expired, need to refresh the flow
|
|
||||||
if (obj.status == 410) {
|
|
||||||
Cookies.set('flow_state','flow_expired');
|
|
||||||
// If we call the page without arguments, we get a new flow
|
|
||||||
window.location.href = 'login';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called after a POST on settings. It tells if the save was
|
// This is called after a POST on settings. It tells if the save was
|
||||||
// successful and display / handles based on that outcome
|
// successful and display / handles based on that outcome
|
||||||
function flow_settings_validate() {
|
function flow_settings_validate() {
|
||||||
|
var flow = $.urlParam('flow');
|
||||||
|
var uri = api_url + 'self-service/settings/flows?id=' + flow;
|
||||||
|
|
||||||
var flow = $.urlParam('flow');
|
$.ajax({
|
||||||
var uri = api_url + 'self-service/settings/flows?id=' + flow;
|
type: 'GET',
|
||||||
|
url: uri,
|
||||||
|
success: function (data) {
|
||||||
|
// We had success. We save that fact in our flow_state
|
||||||
|
// cookie and regenerate a new flow
|
||||||
|
if (data.state == 'success') {
|
||||||
|
Cookies.set('flow_state', 'settings_saved');
|
||||||
|
|
||||||
$.ajax( {
|
// Redirect to generate new flow ID
|
||||||
type: "GET",
|
window.location.href = 'settings';
|
||||||
url: uri,
|
} else {
|
||||||
success: function(data) {
|
// There was an error, Kratos does not specify what is
|
||||||
|
// wrong. So we just show the general error message and
|
||||||
|
// let the user figure it out. We can re-use the flow-id
|
||||||
|
$('#contentProfileSaveFailed').show();
|
||||||
|
|
||||||
// We had success. We save that fact in our flow_state
|
// For now, this code assumes that only the password can fail
|
||||||
// cookie and regenerate a new flow
|
// validation. Other forms might need to be added in the future.
|
||||||
if (data.state == 'success') {
|
html = render_form(data, 'password');
|
||||||
Cookies.set('flow_state', 'settings_saved');
|
$('#contentPassword').html(html);
|
||||||
|
}
|
||||||
// Redirect to generate new flow ID
|
},
|
||||||
window.location.href = 'settings';
|
});
|
||||||
}
|
|
||||||
else {
|
|
||||||
// There was an error, Kratos does not specify what is
|
|
||||||
// wrong. So we just show the general error message and
|
|
||||||
// let the user figure it out. We can re-use the flow-id
|
|
||||||
$("#contentProfileSaveFailed").show();
|
|
||||||
|
|
||||||
// For now, this code assumes that only the password can fail
|
|
||||||
// validation. Other forms might need to be added in the future.
|
|
||||||
html = render_form(data, 'password')
|
|
||||||
$("#contentPassword").html(html)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Render the settings flow, this is where users can change their personal
|
// Render the settings flow, this is where users can change their personal
|
||||||
// settings, like name and password. The form contents are defined by Kratos
|
// settings, like name and password. The form contents are defined by Kratos
|
||||||
function flow_settings() {
|
function flow_settings() {
|
||||||
|
// Get the details from the current flow from kratos
|
||||||
|
var flow = $.urlParam('flow');
|
||||||
|
var uri = api_url + 'self-service/settings/flows?id=' + flow;
|
||||||
|
$.ajax({
|
||||||
|
type: 'GET',
|
||||||
|
url: uri,
|
||||||
|
success: function (data) {
|
||||||
|
var state = Cookies.get('flow_state');
|
||||||
|
|
||||||
// Get the details from the current flow from kratos
|
// If we have confirmation the settings are saved, show the
|
||||||
var flow = $.urlParam('flow');
|
// notification
|
||||||
var uri = api_url + 'self-service/settings/flows?id=' + flow;
|
if (state == 'settings_saved') {
|
||||||
$.ajax({
|
$('#contentProfileSaved').show();
|
||||||
type: "GET",
|
Cookies.set('flow_state', 'settings');
|
||||||
url: uri,
|
}
|
||||||
success: function(data) {
|
|
||||||
|
|
||||||
var state = Cookies.get('flow_state')
|
// Hide prfile section if we are in recovery state
|
||||||
|
// so the user is not confused by other fields. The user
|
||||||
|
// probably want to setup a password only first.
|
||||||
|
if (state == 'recovery') {
|
||||||
|
$('#contentProfile').hide();
|
||||||
|
}
|
||||||
|
|
||||||
// If we have confirmation the settings are saved, show the
|
// Render the password & profile form based on the fields we got
|
||||||
// notification
|
// from the API
|
||||||
if (state == 'settings_saved') {
|
var html = render_form(data, 'password');
|
||||||
$("#contentProfileSaved").show();
|
$('#contentPassword').html(html);
|
||||||
Cookies.set('flow_state', 'settings');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide prfile section if we are in recovery state
|
html = render_form(data, 'profile');
|
||||||
// so the user is not confused by other fields. The user
|
$('#contentProfile').html(html);
|
||||||
// probably want to setup a password only first.
|
|
||||||
if (state == 'recovery') {
|
|
||||||
$("#contentProfile").hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// If the submit button is hit, execute the POST with Ajax.
|
||||||
|
$('#formpassword').submit(function (e) {
|
||||||
|
// avoid to execute the actual submit of the form.
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
// Render the password & profile form based on the fields we got
|
var form = $(this);
|
||||||
// from the API
|
var url = form.attr('action');
|
||||||
var html = render_form(data, 'password');
|
|
||||||
$("#contentPassword").html(html);
|
|
||||||
|
|
||||||
html = render_form(data, 'profile');
|
|
||||||
$("#contentProfile").html(html);
|
|
||||||
|
|
||||||
// If the submit button is hit, execute the POST with Ajax.
|
|
||||||
$("#formpassword").submit(function(e) {
|
|
||||||
|
|
||||||
// avoid to execute the actual submit of the form.
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
var form = $(this);
|
|
||||||
var url = form.attr('action');
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: url,
|
|
||||||
data: form.serialize(),
|
|
||||||
complete: function(obj) {
|
|
||||||
// Validate the settings
|
|
||||||
flow_settings_validate();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
complete: function(obj) {
|
|
||||||
|
|
||||||
// If we get a 410, the flow is expired, need to refresh the flow
|
|
||||||
if (obj.status == 410) {
|
|
||||||
Cookies.set('flow_state','flow_expired');
|
|
||||||
window.location.href = 'settings';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: url,
|
||||||
|
data: form.serialize(),
|
||||||
|
complete: function (obj) {
|
||||||
|
// Validate the settings
|
||||||
|
flow_settings_validate();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
complete: function (obj) {
|
||||||
|
// If we get a 410, the flow is expired, need to refresh the flow
|
||||||
|
if (obj.status == 410) {
|
||||||
|
Cookies.set('flow_state', 'flow_expired');
|
||||||
|
window.location.href = 'settings';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function flow_recover() {
|
function flow_recover() {
|
||||||
var flow = $.urlParam('flow');
|
var flow = $.urlParam('flow');
|
||||||
var uri = api_url + 'self-service/recovery/flows?id=' + flow;
|
var uri = api_url + 'self-service/recovery/flows?id=' + flow;
|
||||||
|
|
||||||
$.ajax( {
|
$.ajax({
|
||||||
type: "GET",
|
type: 'GET',
|
||||||
url: uri,
|
url: uri,
|
||||||
success: function(data) {
|
success: function (data) {
|
||||||
|
// Render the recover form, method 'link'
|
||||||
|
var html = render_form(data, 'link');
|
||||||
|
$('#contentRecover').html(html);
|
||||||
|
|
||||||
// Render the recover form, method 'link'
|
// Do form post as an AJAX call
|
||||||
var html = render_form(data, 'link');
|
$('#formlink').submit(function (e) {
|
||||||
$("#contentRecover").html(html);
|
// avoid to execute the actual submit of the form.
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
// Do form post as an AJAX call
|
var form = $(this);
|
||||||
$("#formlink").submit(function(e) {
|
var url = form.attr('action');
|
||||||
|
|
||||||
// avoid to execute the actual submit of the form.
|
// keep stat we are in recovery
|
||||||
e.preventDefault();
|
Cookies.set('flow_state', 'recovery');
|
||||||
|
$.ajax({
|
||||||
var form = $(this);
|
type: 'POST',
|
||||||
var url = form.attr('action');
|
url: url,
|
||||||
|
data: form.serialize(), // serializes the form's elements.
|
||||||
// keep stat we are in recovery
|
success: function (data) {
|
||||||
Cookies.set('flow_state', 'recovery');
|
// Show the request is sent out
|
||||||
$.ajax({
|
$('#contentRecover').hide();
|
||||||
type: "POST",
|
$('#contentRecoverRequested').show();
|
||||||
url: url,
|
},
|
||||||
data: form.serialize(), // serializes the form's elements.
|
});
|
||||||
success: function(data)
|
});
|
||||||
{
|
},
|
||||||
|
complete: function (obj) {
|
||||||
// Show the request is sent out
|
// If we get a 410, the flow is expired, need to refresh the flow
|
||||||
$("#contentRecover").hide();
|
if (obj.status == 410) {
|
||||||
$("#contentRecoverRequested").show();
|
Cookies.set('flow_state', 'flow_expired');
|
||||||
}
|
window.location.href = 'recovery';
|
||||||
});
|
}
|
||||||
});
|
},
|
||||||
|
});
|
||||||
|
|
||||||
},
|
|
||||||
complete: function(obj) {
|
|
||||||
|
|
||||||
// If we get a 410, the flow is expired, need to refresh the flow
|
|
||||||
if (obj.status == 410) {
|
|
||||||
Cookies.set('flow_state','flow_expired');
|
|
||||||
window.location.href = 'recovery';
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Based on Kratos UI data and a group name, get the full form for that group.
|
// Based on Kratos UI data and a group name, get the full form for that group.
|
||||||
// kratos groups elements which belongs together in a group and should be posted
|
// kratos groups elements which belongs together in a group and should be posted
|
||||||
// at once. The elements in the default group should be part of all other
|
// at once. The elements in the default group should be part of all other
|
||||||
// groups.
|
// groups.
|
||||||
//
|
//
|
||||||
// data: data object as returned form the API
|
// data: data object as returned form the API
|
||||||
// group: group to render.
|
// group: group to render.
|
||||||
function render_form(data, group) {
|
function render_form(data, group) {
|
||||||
|
// Create form
|
||||||
|
var action = data.ui.action;
|
||||||
|
var method = data.ui.method;
|
||||||
|
var form = "<form id='form" + group + "' method='" + method + "' action='" + action + "'>";
|
||||||
|
|
||||||
// Create form
|
for (const node of data.ui.nodes) {
|
||||||
var action = data.ui.action;
|
var name = node.attributes.name;
|
||||||
var method = data.ui.method;
|
var type = node.attributes.type;
|
||||||
var form = "<form id='form"+group+"' method='"+method+"' action='"+action+"'>";
|
var value = node.attributes.value;
|
||||||
|
var messages = node.messages;
|
||||||
|
|
||||||
for (const node of data.ui.nodes) {
|
if (node.group == 'default' || node.group == group) {
|
||||||
|
var elm = getFormElement(type, name, value, messages);
|
||||||
var name = node.attributes.name;
|
form += elm;
|
||||||
var type = node.attributes.type;
|
|
||||||
var value = node.attributes.value;
|
|
||||||
var messages = node.messages
|
|
||||||
|
|
||||||
if (node.group == 'default' || node.group == group) {
|
|
||||||
var elm = getFormElement(type, name, value, messages);
|
|
||||||
form += elm;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
form += "</form>";
|
}
|
||||||
return form;
|
form += '</form>';
|
||||||
|
return form;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there are any general messages to show to the user and render them
|
||||||
|
function render_messages(data) {
|
||||||
|
var messages = data.ui.messages;
|
||||||
|
if (messages == []) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
var html = '<ul>';
|
||||||
|
messages.forEach((message) => {
|
||||||
|
html += '<li>';
|
||||||
|
html += message.text;
|
||||||
|
html += '</li>';
|
||||||
|
});
|
||||||
|
html += '</ul>';
|
||||||
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return form element based on name, including help text (sub), placeholder etc.
|
// Return form element based on name, including help text (sub), placeholder etc.
|
||||||
// Kratos give us form names and types and specifies what to render. However
|
// Kratos give us form names and types and specifies what to render. However
|
||||||
// it does not provide labels or translations. This function returns a HTML
|
// it does not provide labels or translations. This function returns a HTML
|
||||||
// form element based on the fields provided by Kratos with proper names and
|
// form element based on the fields provided by Kratos with proper names and
|
||||||
// labels
|
// labels
|
||||||
// type: input type, usual "input", "hidden" or "submit". But bootstrap types
|
// type: input type, usual "input", "hidden" or "submit". But bootstrap types
|
||||||
// like "email" are also supported
|
// like "email" are also supported
|
||||||
|
@ -274,98 +261,80 @@ function render_form(data, group) {
|
||||||
// value: If there is already a value known, show it
|
// value: If there is already a value known, show it
|
||||||
// messages: error messages related to the field
|
// messages: error messages related to the field
|
||||||
function getFormElement(type, name, value, messages) {
|
function getFormElement(type, name, value, messages) {
|
||||||
console.log("Getting form element", type, name, value, messages)
|
console.log('Getting form element', type, name, value, messages);
|
||||||
|
|
||||||
if (value == undefined) {
|
if (value == undefined) {
|
||||||
value = '';
|
value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof(messages) == "undefined") {
|
if (typeof messages == 'undefined') {
|
||||||
messages = []
|
messages = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name == 'email' || name == 'traits.email') {
|
if (name == 'email' || name == 'traits.email') {
|
||||||
return getFormInput(
|
return getFormInput(
|
||||||
'email',
|
'email',
|
||||||
name,
|
name,
|
||||||
value,
|
value,
|
||||||
'E-mail address',
|
'E-mail address',
|
||||||
'Please enter your e-mail address here',
|
'Please enter your e-mail address here',
|
||||||
'Please provide your e-mail address. We will send a recovery ' +
|
'Please provide your e-mail address. We will send a recovery link to that e-mail address.',
|
||||||
'link to that e-mail address.',
|
messages,
|
||||||
messages,
|
);
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (name == 'traits.username') {
|
if (name == 'traits.username') {
|
||||||
return getFormInput(
|
return getFormInput('name', name, value, 'Username', 'Please provide an username', null, messages);
|
||||||
'name',
|
}
|
||||||
name,
|
|
||||||
value,
|
|
||||||
'Username',
|
|
||||||
'Please provide an username',
|
|
||||||
null,
|
|
||||||
messages,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name == 'traits.name') {
|
if (name == 'traits.name') {
|
||||||
return getFormInput(
|
return getFormInput('name', name, value, 'Full name', 'Please provide your full name', null, messages);
|
||||||
'name',
|
}
|
||||||
name,
|
|
||||||
value,
|
|
||||||
'Full name',
|
|
||||||
'Please provide your full name',
|
|
||||||
null,
|
|
||||||
messages,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (name == 'identifier') {
|
||||||
|
return getFormInput(
|
||||||
|
'email',
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
'E-mail address',
|
||||||
|
'Please provide your e-mail address to log in',
|
||||||
|
null,
|
||||||
|
messages,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (name == 'identifier') {
|
if (name == 'password') {
|
||||||
return getFormInput(
|
return getFormInput('password', name, value, 'Password', 'Please provide your password', null, messages);
|
||||||
'email',
|
}
|
||||||
name,
|
|
||||||
value,
|
|
||||||
'E-mail address',
|
|
||||||
'Please provide your e-mail address to log in',
|
|
||||||
null,
|
|
||||||
messages,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name == 'password') {
|
if (type == 'hidden' || name == 'traits.uuid') {
|
||||||
return getFormInput(
|
return (
|
||||||
'password',
|
`
|
||||||
name,
|
<input type="hidden" class="form-control" id="` +
|
||||||
value,
|
name +
|
||||||
'Password',
|
`"
|
||||||
'Please provide your password',
|
name="` +
|
||||||
null,
|
name +
|
||||||
messages,
|
`" value='` +
|
||||||
);
|
value +
|
||||||
}
|
`'>`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == 'submit') {
|
||||||
if (type == 'hidden' || name == 'traits.uuid') {
|
return (
|
||||||
|
`<div class="form-group">
|
||||||
return `
|
<input type="hidden" name="` +
|
||||||
<input type="hidden" class="form-control" id="`+name+`"
|
name +
|
||||||
name="`+name+`" value='`+value+`'>`;
|
`" value="` +
|
||||||
}
|
value +
|
||||||
|
`">
|
||||||
if (type == 'submit') {
|
|
||||||
|
|
||||||
return `<div class="form-group">
|
|
||||||
<input type="hidden" name="`+name+`" value="`+value+`">
|
|
||||||
<button type="submit" class="btn btn-primary">Go!</button>
|
<button type="submit" class="btn btn-primary">Go!</button>
|
||||||
</div>`;
|
</div>`
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return getFormInput('input', name, value, name, null,null, messages);
|
|
||||||
|
|
||||||
|
|
||||||
|
return getFormInput('input', name, value, name, null, null, messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Usually called by getFormElement, generic function to generate an
|
// Usually called by getFormElement, generic function to generate an
|
||||||
|
@ -378,56 +347,58 @@ function getFormElement(type, name, value, messages) {
|
||||||
// param help: Additional help text, displayed below the field in small font
|
// param help: Additional help text, displayed below the field in small font
|
||||||
// param messages: Message about failed input
|
// param messages: Message about failed input
|
||||||
function getFormInput(type, name, value, label, placeHolder, help, messages) {
|
function getFormInput(type, name, value, label, placeHolder, help, messages) {
|
||||||
if (typeof(help) == "undefined" || help == null) {
|
if (typeof help == 'undefined' || help == null) {
|
||||||
help = ""
|
help = '';
|
||||||
}
|
}
|
||||||
console.log("Messages: ", messages);
|
console.log('Messages: ', messages);
|
||||||
|
|
||||||
// Id field for help element
|
// Id field for help element
|
||||||
var nameHelp = name + "Help";
|
var nameHelp = name + 'Help';
|
||||||
|
|
||||||
var element = '<div class="form-group">';
|
var element = '<div class="form-group">';
|
||||||
element += '<label for="'+name+'">'+label+'</label>';
|
element += '<label for="' + name + '">' + label + '</label>';
|
||||||
element += '<input type="'+type+'" class="form-control" id="'+name+'" name="'+name+'" ';
|
element += '<input type="' + type + '" class="form-control" id="' + name + '" name="' + name + '" ';
|
||||||
|
|
||||||
// messages get appended to help info
|
// messages get appended to help info
|
||||||
if (messages.length) {
|
if (messages.length) {
|
||||||
for (message in messages) {
|
for (message in messages) {
|
||||||
console.log("adding message", messages[message])
|
console.log('adding message', messages[message]);
|
||||||
help += messages[message]['text']
|
help += messages[message]['text'];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If we are a password field, add a eye icon to reveal password
|
// If we are a password field, add a eye icon to reveal password
|
||||||
if (value) {
|
if (value) {
|
||||||
element += 'value="'+value+'" ';
|
element += 'value="' + value + '" ';
|
||||||
}
|
}
|
||||||
if (help) {
|
if (help) {
|
||||||
element += 'aria-describedby="' + nameHelp +'" ';
|
element += 'aria-describedby="' + nameHelp + '" ';
|
||||||
}
|
}
|
||||||
if (placeHolder) {
|
if (placeHolder) {
|
||||||
element += 'placeholder="'+placeHolder+'" ';
|
element += 'placeholder="' + placeHolder + '" ';
|
||||||
}
|
}
|
||||||
element += ">";
|
element += '>';
|
||||||
|
|
||||||
if (help) {
|
if (help) {
|
||||||
element +=
|
element +=
|
||||||
`<small id="`+nameHelp+`" class="form-text text-muted">` + help + `
|
`<small id="` +
|
||||||
|
nameHelp +
|
||||||
|
`" class="form-text text-muted">` +
|
||||||
|
help +
|
||||||
|
`
|
||||||
</small>`;
|
</small>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
element += '</div>';
|
element += '</div>';
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// $.urlParam get parameters from the URI. Example: id = $.urlParam('id');
|
// $.urlParam get parameters from the URI. Example: id = $.urlParam('id');
|
||||||
$.urlParam = function(name) {
|
$.urlParam = function (name) {
|
||||||
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
|
var results = new RegExp('[?&]' + name + '=([^&#]*)').exec(window.location.href);
|
||||||
if (results==null) {
|
if (results == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return decodeURI(results[1]) || 0;
|
return decodeURI(results[1]) || 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
@ -17,11 +15,9 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="contentMessages"></div>
|
<div id="contentMessages"></div>
|
||||||
<div id="contentWelcome">Welcome {{ id['name'] }},<br/><br/>
|
<div id="contentWelcome">
|
||||||
You are already logged in.
|
Welcome{{ name }}, you are logged in.
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<div id="contentMessages"></div>
|
<div id="contentMessages"></div>
|
||||||
<div id="contentLogin"></div>
|
<div id="contentLogin"></div>
|
||||||
<div id="contentHelp">
|
<div id="contentHelp">
|
||||||
<a href='recovery'>Forget password?</a> | <a href='https://stackspin.net'>About stackspin</a>
|
<a href='recovery'>Set new password</a> | <a href='https://stackspin.net'>About stackspin</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
Loading…
Reference in a new issue