feat: Update versioning and improve UI layouts

This commit introduces several UI enhancements, a change to the default trash bin behavior, and a versioning scheme update.

- **Versioning**:
  - The project's versioning scheme has been updated from  to  to better reflect its maturity.
  - The  and  have been updated to document this change.

- **Global Trash Default**:
  - The default behavior for the global trash setting is now "disabled".
  - The backend logic in  was updated to reflect this, defaulting to  if the setting is not present in the database.
  - The  API endpoint now correctly updates all lists to reflect the new global state (enabled or disabled).

- **Admin Panel Layout**:
  - In the "Create User" form, the email field is now on its own wider row () for better readability.
  - In the user list, the user's email is now displayed on a separate line below the username for clarity.

- **Settings Modal Layout**:
  - The "Change Password" fields are now stacked vertically, each occupying .
  - The settings modal is now narrower (removed ).
This commit is contained in:
2025-12-24 12:07:55 +01:00
parent be4596e2f3
commit 00e8073788
4 changed files with 58 additions and 30 deletions

View File

@@ -2,6 +2,20 @@ Changelog for Noteshop
## [Unreleased]
## 24.12.2025
- **Default Settings & UI Improvements**:
- Changed the default behavior for the global trash setting to "disabled" to make its use optional.
- Improved the layout in the Admin Panel:
- In the user list, the email address is now displayed neatly below the username.
- In the "Create User" form, the email field has been moved to its own wider row to improve readability.
- Adjusted the layout in the Settings Modal for better usability:
- The "Change Password" fields are now clearly arranged one below the other.
- The settings window has been made narrower for a more compact view.
- **Versioning**:
- Updated the versioning scheme from `0.1.0.x` to `1.0.x` to signify a more mature state of the project.
## 22.12.2025
- **Password Reset and Email Security**:
@@ -39,4 +53,4 @@ Changelog for Noteshop
- Implemented real-time updates for the shopping list.
- Added Gitea Issues link to README.md for support and feedback.
- Fixed an issue where the delete password prompt did not show for all users.
- Fixed an issue where the delete password prompt did not show for all users.

View File

@@ -6,13 +6,17 @@ This project provides a central, self-hosted web application for a family or gro
This web service is the final development step for the accompanying **Android app**. The goal is to allow the app to automatically sync with this web service.
**Current Status & Workaround:** While direct API integration in the app is still to be completed, the system is already fully functional using notifications. The text sent in the Gotify notification can be copied and pasted 1:1 into the Android app to instantly populate the shopping list.
**Current Status & Integration:** The direct API integration for importing items into the Android app is now fully functional. Gotify notifications have been enhanced to include the username and the specific list name where items/tasks were added, facilitating better assignment within the app. The option to include the username in notifications can be configured in the Admin Panel. Future updates to the Android app will also include a feature to notify users about unimported items/tasks from the web app (if the list names match and the web app is configured), making web app notifications optional.
## Versioning
The project has adopted a new versioning scheme. As of `1.0.12`, the version format is `1.0.x`, moving away from the previous `0.1.0.x` scheme to better reflect the project's maturity.
## Android App
The app is registered with F-Droid and will be available there soon.
For the impatient, the signed Android app can be downloaded in advance starting from version **[0.1.177](https://git.ilunix.de/punix/noteshop/releases/tag/0.1.177)**. This is the same version that will later be available on F-Droid and is compatible with web app version `0.1.0.9`.
For the impatient, the signed Android app can be downloaded in advance starting from version **[0.1.177](https://git.ilunix.de/punix/noteshop/releases/tag/0.1.177)**. This is the same version that will later be available on F-Droid and is compatible with web app version 1.0.12 and later.
**Disclaimer:** Installing apps from unknown sources always carries a security risk. It is strongly recommended to wait for the official release on F-Droid. The app is provided without any guarantee.

11
main.py
View File

@@ -1309,8 +1309,8 @@ async def get_global_use_trash(current_user: User = Depends(get_current_active_u
"SELECT value FROM app_settings WHERE key = 'global_use_trash'")
result = cursor.fetchone()
conn.close()
# Default to True if not set
is_enabled = result[0] == '1' if result else True
# Default to False if not set
is_enabled = result[0] == '1' if result else False
return {"enabled": is_enabled}
@@ -1327,11 +1327,12 @@ async def set_global_use_trash(request: UseTrashSetting, current_user: User = De
cursor.execute("INSERT OR REPLACE INTO app_settings (key, value) VALUES (?, ?)",
('global_use_trash', value_to_store_setting))
# When the admin toggles the global setting, all lists should default to using the trash.
# When the admin toggles the global setting, this should be reflected in all lists.
# If the global setting is enabled, this is enforced.
# If it's disabled, lists are reset to the default 'on' state, giving control back to the user.
# If it's disabled, we turn it off for all lists.
update_value = 1 if request.enabled else 0
cursor.execute(
"UPDATE shopping_lists SET use_trash = 1 WHERE name != 'Papierkorb'")
"UPDATE shopping_lists SET use_trash = ? WHERE name != 'Papierkorb'", (update_value,))
conn.commit()
conn.close()

View File

@@ -439,25 +439,27 @@
<h5 id="create-user-title" class="card-title"></h5>
<form id="create-user-form">
<div class="row">
<div class="col-md-3 mb-3">
<div class="col-md-4 mb-3">
<label id="username-label" for="new-username" class="form-label"></label>
<input type="text" id="new-username" class="form-control" required>
</div>
<div class="col-md-3 mb-3">
<div class="col-md-4 mb-3">
<label id="password-label" for="new-password" class="form-label"></label>
<input type="password" id="new-password" class="form-control" required>
</div>
<div class="col-md-3 mb-3">
<label id="email-label" for="new-user-email" class="form-label"></label>
<input type="email" id="new-user-email" class="form-control">
</div>
<div class="col-md-3 mb-3 d-flex align-items-end">
<div class="col-md-4 mb-3 d-flex align-items-end">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="new-user-is-admin">
<label id="is-admin-label" class="form-check-label" for="new-user-is-admin"></label>
</div>
</div>
</div>
<div class="row">
<div class="col-md-7 mb-3">
<label id="email-label" for="new-user-email" class="form-label"></label>
<input type="email" id="new-user-email" class="form-control">
</div>
</div>
<button id="create-user-button" type="submit" class="btn btn-success"></button>
<div id="create-user-status" class="mt-2"></div>
</form>
@@ -495,7 +497,7 @@
</div>
<form id="set-deletion-password-form">
<div class="row">
<div class="col-md-6 mb-3">
<div class="col-md-7 mb-3">
<div class="input-group">
<input type="password" id="deletion-password" class="form-control" required>
<button class="btn btn-outline-secondary" type="button" id="toggle-deletion-password">
@@ -618,7 +620,7 @@
<!-- Settings Modal -->
<div class="modal fade" id="settings-modal" tabindex="-1" aria-labelledby="settings-modal-label" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="settings-modal-label"></h5>
@@ -627,7 +629,7 @@
<div class="modal-body">
<h5 id="update-email-title" class="card-title"></h5>
<form id="email-update-form">
<div class="mb-3">
<div class="col-md-7 mb-3">
<label for="user-email-input" class="form-label" id="user-email-label"></label>
<input type="email" class="form-control" id="user-email-input">
</div>
@@ -638,15 +640,19 @@
<h5 id="change-password-title" class="card-title"></h5>
<form id="change-password-form">
<div class="row">
<div class="col-md-4 mb-3">
<div class="col-md-7 mb-3">
<label id="current-password-label" for="current-password" class="form-label"></label>
<input type="password" id="current-password" class="form-control" required>
</div>
<div class="col-md-4 mb-3">
</div>
<div class="row">
<div class="col-md-7 mb-3">
<label id="new-password-label" for="new-password-change" class="form-label"></label>
<input type="password" id="new-password-change" class="form-control" required>
</div>
<div class="col-md-4 mb-3">
</div>
<div class="row">
<div class="col-md-7 mb-3">
<label id="confirm-password-label" for="confirm-password" class="form-label"></label>
<input type="password" id="confirm-password" class="form-control" required>
</div>
@@ -2409,14 +2415,16 @@
const li = document.createElement('li');
li.className = 'list-group-item d-flex justify-content-between align-items-center';
const userInfo = document.createElement('span');
userInfo.textContent = `${user.username}`;
const userInfoContainer = document.createElement('div');
const usernameLine = document.createElement('div');
usernameLine.textContent = `${user.username}`;
if (user.is_admin) {
const adminBadge = document.createElement('span');
adminBadge.className = 'badge bg-primary rounded-pill ms-2';
adminBadge.textContent = 'Admin';
userInfo.appendChild(adminBadge);
usernameLine.appendChild(adminBadge);
}
if (user.is_locked) {
@@ -2424,17 +2432,18 @@
// TODO: Add translation for "Locked"
lockedBadge.className = 'badge bg-warning text-dark rounded-pill ms-2';
lockedBadge.textContent = 'Locked';
userInfo.appendChild(lockedBadge);
usernameLine.appendChild(lockedBadge);
}
userInfoContainer.appendChild(usernameLine);
if (user.email) {
const emailSpan = document.createElement('span');
emailSpan.className = 'text-muted ms-2';
emailSpan.textContent = `(${user.email})`;
userInfo.appendChild(emailSpan);
const emailLine = document.createElement('div');
emailLine.className = 'text-muted small';
emailLine.textContent = user.email;
userInfoContainer.appendChild(emailLine);
}
li.appendChild(userInfo);
li.appendChild(userInfoContainer);
const buttonContainer = document.createElement('div');