Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion TEKDB/TEKDB/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@


urlpatterns = [
# url(r'^login/', include('login.urls')),
path(
"change_password/",
login_views.TEKDBPasswordChangeView.as_view(),
name="change_password",
),
path("admin/filebrowser/", tekdb_filebrowser.urls),
path("login/", login_views.login, name="login"),
path("login_async/", login_views.login_async, name="login_async"),
Expand Down
4 changes: 0 additions & 4 deletions TEKDB/explore/static/explore/css/forms.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
text-align: center;
}

.registration-form .helptext {
visibility: hidden;
}

input[type="text"],
.form-control,
input[type="password"] {
Expand Down
69 changes: 68 additions & 1 deletion TEKDB/explore/static/explore/js/modals.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ $("#loginModal").on("shown.bs.modal", function () {
const LOGIN_ERROR_MESSAGE = "Invalid username or password";
loginForm.addEventListener("submit", function (event) {
event.preventDefault();
var signIn = account.signIn(event, this, function (success) {
account.signIn(event, this, function (success) {
if (success) {
$("#loginModal").modal("hide");
const exploreLink = document.querySelector(".nav-explore");
Expand All @@ -19,3 +19,70 @@ $("#loginModal").on("shown.bs.modal", function () {
});
});
});

$("#changePasswordModal").on("shown.bs.modal", function () {
const changePasswordForm = document.querySelector("#changePasswordModal form");

changePasswordForm.addEventListener("submit", function (event) {
event.preventDefault();
account.changePassword(event, this, function (response) {
if (response.success) {
// clear any previous error messages
const errorLists = document.querySelectorAll("#changePasswordModal ul");
if (errorLists.length) {
errorLists.forEach((list) => list.remove());
}
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On successful password change you remove <ul> error lists, but you don’t clear the red border-color styling that was applied to invalid inputs. If the user fixes errors and then succeeds without closing the modal, the inputs can remain styled as invalid. Consider clearing the input error styles in the success branch (similar to the hidden.bs.modal cleanup).

Suggested change
}
}
// reset input border color
const passwordInputs = document.querySelectorAll("#changePasswordModal input[type='password']");
passwordInputs.forEach((input) => input.setAttribute("style", ""));

Copilot uses AI. Check for mistakes.
// clear any previous success message
const previousSuccessMessage = document.querySelector("#changePasswordSuccessMessage");
if (!previousSuccessMessage) {
// display success message
const successMessage = document.createElement("p");
successMessage.setAttribute("id", "changePasswordSuccessMessage");
successMessage.textContent = "Password successfully changed!";
successMessage.setAttribute("style", "color: green;");
successMessage.setAttribute("class", "m-0");

// insert success message after submit button
const submitButton = changePasswordForm.querySelector('#changePasswordSubmit');
submitButton.after(successMessage);
}

// reset form
changePasswordForm.reset();
} else {
// display error messages
for (const elementId in response.data.data) {
const errorList = document.createElement("ul");
const erroredInput = document.querySelector(`#${elementId}`);
erroredInput.after(errorList);
erroredInput.setAttribute("style", "border-color: red;");
Comment on lines +53 to +58
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When handling a failed submission, the code appends new <ul> error lists after each input but doesn’t clear any existing error lists first. Submitting the form multiple times with errors will duplicate error messages in the modal. Clear prior error lists (and potentially reset input styles) before rendering the new errors.

Copilot uses AI. Check for mistakes.
if (response.data.data[elementId].length > 0) {
for (const error in response.data.data[elementId]) {
const listItem = document.createElement("li");
listItem.textContent = response.data.data[elementId][error];
errorList.appendChild(listItem);
}

}
}
}
});
Comment on lines +23 to +69
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The submit handler for the change-password form is registered inside the shown.bs.modal callback. Every time the modal is opened, a new submit listener is added, which will cause multiple AJAX submissions on later opens. Bind the handler once (e.g., on DOM ready) or remove an existing listener before adding a new one.

Suggested change
$("#changePasswordModal").on("shown.bs.modal", function () {
const changePasswordForm = document.querySelector("#changePasswordModal form");
changePasswordForm.addEventListener("submit", function (event) {
event.preventDefault();
account.changePassword(event, this, function (response) {
if (response.success) {
// clear any previous error messages
const errorLists = document.querySelectorAll("#changePasswordModal ul");
if (errorLists.length) {
errorLists.forEach((list) => list.remove());
}
// clear any previous success message
const previousSuccessMessage = document.querySelector("#changePasswordSuccessMessage");
if (!previousSuccessMessage) {
// display success message
const successMessage = document.createElement("p");
successMessage.setAttribute("id", "changePasswordSuccessMessage");
successMessage.textContent = "Password successfully changed!";
successMessage.setAttribute("style", "color: green;");
successMessage.setAttribute("class", "m-0");
// insert success message after submit button
const submitButton = changePasswordForm.querySelector('#changePasswordSubmit');
submitButton.after(successMessage);
}
// reset form
changePasswordForm.reset();
} else {
// display error messages
for (const elementId in response.data.data) {
const errorList = document.createElement("ul");
const erroredInput = document.querySelector(`#${elementId}`);
erroredInput.after(errorList);
erroredInput.setAttribute("style", "border-color: red;");
if (response.data.data[elementId].length > 0) {
for (const error in response.data.data[elementId]) {
const listItem = document.createElement("li");
listItem.textContent = response.data.data[elementId][error];
errorList.appendChild(listItem);
}
}
}
}
});
const changePasswordForm = document.querySelector("#changePasswordModal form");
changePasswordForm.addEventListener("submit", function (event) {
event.preventDefault();
account.changePassword(event, this, function (response) {
if (response.success) {
// clear any previous error messages
const errorLists = document.querySelectorAll("#changePasswordModal ul");
if (errorLists.length) {
errorLists.forEach((list) => list.remove());
}
// clear any previous success message
const previousSuccessMessage = document.querySelector("#changePasswordSuccessMessage");
if (!previousSuccessMessage) {
// display success message
const successMessage = document.createElement("p");
successMessage.setAttribute("id", "changePasswordSuccessMessage");
successMessage.textContent = "Password successfully changed!";
successMessage.setAttribute("style", "color: green;");
successMessage.setAttribute("class", "m-0");
// insert success message after submit button
const submitButton = changePasswordForm.querySelector('#changePasswordSubmit');
submitButton.after(successMessage);
}
// reset form
changePasswordForm.reset();
} else {
// display error messages
for (const elementId in response.data.data) {
const errorList = document.createElement("ul");
const erroredInput = document.querySelector(`#${elementId}`);
erroredInput.after(errorList);
erroredInput.setAttribute("style", "border-color: red;");
if (response.data.data[elementId].length > 0) {
for (const error in response.data.data[elementId]) {
const listItem = document.createElement("li");
listItem.textContent = response.data.data[elementId][error];
errorList.appendChild(listItem);
}
}
}
}

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to Copilot's comment

});
});

$("#changePasswordModal").on("hidden.bs.modal", function () {
// clear error messages
const errorLists = document.querySelectorAll("#changePasswordModal ul");
errorLists.forEach((list) => list.remove());
// reset input border color
const passwordInputs = document.querySelectorAll("#changePasswordModal input[type='password']");
passwordInputs.forEach((input) => input.setAttribute("style", ""));
// clear form
document.querySelector("#changePasswordModal form").reset();
// clear success message
const successMessage = document.querySelector("#changePasswordSuccessMessage");

if (successMessage) {
successMessage.remove();
}
});
15 changes: 6 additions & 9 deletions TEKDB/explore/templates/modals.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,32 @@ <h4 class="modal-title" id="loginModalLabel">Please Log In</h4>
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
><i class="bi bi-x-lg text-light"></i></button>
</div>
<div class="modal-body">{% include 'registration/login.html' %}</div>
</div>
</div>
</div>

{% comment %}
<!-- Results Map -->
<div
class="modal fade"
id="resultsMapModal"
id="changePasswordModal"
tabindex="-1"
role="dialog"
aria-labelledby="resultsMapModalLabel"
aria-labelledby="changePasswordModalLabel"
>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="resultsMapModalLabel">Results Map</h4>
<h4 class="modal-title" id="changePasswordModalLabel">Change Password</h4>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
><i class="bi bi-x-lg text-light"></i></button>
</div>
<div class="modal-body">{% include 'results_map.html' %}</div>
<div class="modal-body">{% include 'change_password.html' %}</div>
</div>
</div>
</div>
{% endcomment %}
5 changes: 3 additions & 2 deletions TEKDB/explore/templates/navbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,20 @@
</li>
{% if user.is_authenticated %}
<li class="nav-item dropdown user-menu">
<a class="nav-link dropdown-toggle" hred="#" role="button" id="userDropdown" data-bs-toggle="dropdown" aria-expanded="false">
<a class="nav-link dropdown-toggle" href="#" role="button" id="userDropdown" data-bs-toggle="dropdown" aria-expanded="false">
{{ user.username }}
</a>
<ul class="dropdown-menu" aria-labelledby="userDropdown">
{% if user.is_staff %}
<li><a class="dropdown-item" href="/admin" target="_blank">Administration</a></li>
{% endif %}
<li><a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#changePasswordModal" href="#">Change Password</a></li>
<li><a class="dropdown-item" href="/logout?next=/">Logout</a></li>
</ul>
</li>
{% else %}
<li class="nav-item user-menu">
<a class="header-button nav-link" data-bs-toggle="modal" data-bs-target="#loginModal">
<a class="header-button nav-link" data-bs-toggle="modal" data-bs-target="#loginModal" href="#">
Login
</a>
</li>
Expand Down
23 changes: 23 additions & 0 deletions TEKDB/login/static/login/js/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,28 @@ var account = {
callback(false);
}
});
},
changePassword: function(event, form, callback) {
var formData = $(form).serialize();
var url = '/change_password/';
$.ajax({
url: url,
type: 'POST',
data: formData,
dataType: 'json',
success: function(response) {
if (response.success) {
console.log('%csuccessfully changed password', 'color:green;');
callback({success: true, data: response.data});
} else {
console.log('%cerror changing password: %o', 'color: red;', response.data);
callback({success: false, data: response.data});
}
},
error: function(response) {
console.log('%cerror with change password request submission: %o', 'color: red', response.data);
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the AJAX error callback, response.data is not a standard jQuery jqXHR field (it will typically be undefined). This makes the console message misleading and can hide the actual server response. Log response.responseJSON / response.responseText instead.

Suggested change
console.log('%cerror with change password request submission: %o', 'color: red', response.data);
console.log('%cerror with change password request submission: %o', 'color: red', response.responseJSON || response.responseText);

Copilot uses AI. Check for mistakes.
callback({success: false, data: response.responseJSON});
}
});
}
};
14 changes: 14 additions & 0 deletions TEKDB/login/templates/change_password.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<form method="post" action="{% url 'change_password' %}">
{% csrf_token %}
<div class="form-group">
<label for="old_password">Old Password</label>
<input type="password" class="form-control" id="old_password" name="old_password" placeholder="Old Password" required>
<label for="new_password1">New Password</label>
<input type="password" class="form-control" id="new_password1" name="new_password1" placeholder="New Password" required>
<label for="new_password2">Confirm New Password</label>
<input type="password" class="form-control" id="new_password2" name="new_password2" placeholder="Confirm New Password" required>
</div>
<div class="modal-center">
<input type="submit" class="btn" id="changePasswordSubmit" value="Change My Password">
</div>
</form>
21 changes: 0 additions & 21 deletions TEKDB/login/templates/create.html

This file was deleted.

36 changes: 0 additions & 36 deletions TEKDB/login/templates/forgot.html

This file was deleted.

7 changes: 0 additions & 7 deletions TEKDB/login/templates/registration/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,3 @@
<input type="submit" class="btn" value="Login"><br/>
</div>
</form>
<!--
<div class="modal-center">
<a href="/accounts/register">Request Signup</a>
<span class="splitter">|</span>
<a>Forgot Username or Password</a>
</div>
-->
11 changes: 0 additions & 11 deletions TEKDB/login/templates/registration/registration_form.html

This file was deleted.

Loading