Move settings endpoints to separate blueprint
This commit is contained in:
57
app.py
57
app.py
@@ -23,6 +23,7 @@ from routes.export import export_bp # Import the new export blueprint
|
|||||||
from routes.tags import tags_bp # Import the new tags blueprint
|
from routes.tags import tags_bp # Import the new tags blueprint
|
||||||
from routes.programs import programs_bp # Import the new programs blueprint
|
from routes.programs import programs_bp # Import the new programs blueprint
|
||||||
from routes.exercises import exercises_bp # Import the new exercises blueprint
|
from routes.exercises import exercises_bp # Import the new exercises blueprint
|
||||||
|
from routes.settings import settings_bp # Import the new settings blueprint
|
||||||
from extensions import db
|
from extensions import db
|
||||||
from utils import convert_str_to_date
|
from utils import convert_str_to_date
|
||||||
from flask_htmx import HTMX
|
from flask_htmx import HTMX
|
||||||
@@ -73,6 +74,7 @@ app.register_blueprint(export_bp) # Register the export blueprint (prefix define
|
|||||||
app.register_blueprint(tags_bp) # Register the tags blueprint (prefix defined in blueprint file)
|
app.register_blueprint(tags_bp) # Register the tags blueprint (prefix defined in blueprint file)
|
||||||
app.register_blueprint(programs_bp) # Register the programs blueprint (prefix defined in blueprint file)
|
app.register_blueprint(programs_bp) # Register the programs blueprint (prefix defined in blueprint file)
|
||||||
app.register_blueprint(exercises_bp) # Register the exercises blueprint
|
app.register_blueprint(exercises_bp) # Register the exercises blueprint
|
||||||
|
app.register_blueprint(settings_bp) # Register the settings blueprint
|
||||||
|
|
||||||
@app.after_request
|
@app.after_request
|
||||||
def response_minify(response):
|
def response_minify(response):
|
||||||
@@ -224,62 +226,7 @@ def get_person_name(person_id):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ app.route("/settings")
|
|
||||||
@ login_required
|
|
||||||
def settings():
|
|
||||||
if htmx:
|
|
||||||
return render_block(app.jinja_env, 'settings.html', 'content')
|
|
||||||
return render_template('settings.html')
|
|
||||||
|
|
||||||
@ app.route("/settings/tab/people")
|
|
||||||
@ login_required
|
|
||||||
def settings_people():
|
|
||||||
people = db.get_people()
|
|
||||||
return render_template('partials/settings/people.html', people=people)
|
|
||||||
|
|
||||||
@ app.route("/settings/tab/exercises")
|
|
||||||
@ login_required
|
|
||||||
def settings_exercises():
|
|
||||||
exercises = db.get_all_exercises()
|
|
||||||
all_attributes = db.exercises.get_attributes_by_category()
|
|
||||||
categories_list = db.exercises.get_all_attribute_categories()
|
|
||||||
|
|
||||||
# Format options for custom_select
|
|
||||||
formatted_options = {}
|
|
||||||
for cat, attrs in all_attributes.items():
|
|
||||||
formatted_options[cat] = [{"id": a['attribute_id'], "attribute_id": a['attribute_id'], "name": a['name'], "category_id": a['category_id']} for a in attrs]
|
|
||||||
|
|
||||||
return render_template('partials/settings/exercises.html',
|
|
||||||
exercises=exercises,
|
|
||||||
all_attributes=formatted_options,
|
|
||||||
categories_list=categories_list)
|
|
||||||
|
|
||||||
@ app.route("/settings/tab/export")
|
|
||||||
@ login_required
|
|
||||||
def settings_export():
|
|
||||||
return render_template('partials/settings/export.html')
|
|
||||||
|
|
||||||
@ app.route("/settings/tab/activity")
|
|
||||||
@ login_required
|
|
||||||
def settings_activity():
|
|
||||||
return render_template('partials/settings/activity.html')
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/settings/activity_logs")
|
|
||||||
@login_required
|
|
||||||
def settings_activity_logs():
|
|
||||||
limit = 50
|
|
||||||
offset = request.args.get('offset', 0, type=int)
|
|
||||||
logs = db.activityRequest.get_recent_logs(limit=limit, offset=offset)
|
|
||||||
|
|
||||||
# Check if there are more logs to load
|
|
||||||
has_more = len(logs) == limit
|
|
||||||
|
|
||||||
return render_template('partials/activity_logs.html',
|
|
||||||
logs=logs,
|
|
||||||
offset=offset,
|
|
||||||
limit=limit,
|
|
||||||
has_more=has_more)
|
|
||||||
|
|
||||||
|
|
||||||
# Routes moved to routes/tags.py blueprint
|
# Routes moved to routes/tags.py blueprint
|
||||||
|
|||||||
64
routes/settings.py
Normal file
64
routes/settings.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
from flask import Blueprint, render_template, request
|
||||||
|
from flask_login import login_required
|
||||||
|
from jinja2_fragments import render_block
|
||||||
|
from extensions import db
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
|
settings_bp = Blueprint('settings', __name__)
|
||||||
|
|
||||||
|
@settings_bp.route("/settings")
|
||||||
|
@login_required
|
||||||
|
def settings():
|
||||||
|
# Detect HTMX via header since we don't have the global htmx object here
|
||||||
|
is_htmx = request.headers.get('HX-Request') == 'true'
|
||||||
|
if is_htmx:
|
||||||
|
return render_block(current_app.jinja_env, 'settings.html', 'content')
|
||||||
|
return render_template('settings.html')
|
||||||
|
|
||||||
|
@settings_bp.route("/settings/tab/people")
|
||||||
|
@login_required
|
||||||
|
def settings_people():
|
||||||
|
people = db.get_people()
|
||||||
|
return render_template('partials/settings/people.html', people=people)
|
||||||
|
|
||||||
|
@settings_bp.route("/settings/tab/exercises")
|
||||||
|
@login_required
|
||||||
|
def settings_exercises():
|
||||||
|
exercises = db.get_all_exercises()
|
||||||
|
all_attributes = db.exercises.get_attributes_by_category()
|
||||||
|
categories_list = db.exercises.get_all_attribute_categories()
|
||||||
|
|
||||||
|
# Format options for custom_select
|
||||||
|
formatted_options = {}
|
||||||
|
for cat, attrs in all_attributes.items():
|
||||||
|
formatted_options[cat] = [{"id": a['attribute_id'], "attribute_id": a['attribute_id'], "name": a['name'], "category_id": a['category_id']} for a in attrs]
|
||||||
|
|
||||||
|
return render_template('partials/settings/exercises.html',
|
||||||
|
exercises=exercises,
|
||||||
|
all_attributes=formatted_options,
|
||||||
|
categories_list=categories_list)
|
||||||
|
|
||||||
|
@settings_bp.route("/settings/tab/export")
|
||||||
|
@login_required
|
||||||
|
def settings_export():
|
||||||
|
return render_template('partials/settings/export.html')
|
||||||
|
|
||||||
|
@settings_bp.route("/settings/tab/activity")
|
||||||
|
@login_required
|
||||||
|
def settings_activity():
|
||||||
|
return render_template('partials/settings/activity.html')
|
||||||
|
|
||||||
|
@settings_bp.route("/settings/activity_logs")
|
||||||
|
@login_required
|
||||||
|
def settings_activity_logs():
|
||||||
|
limit = 50
|
||||||
|
offset = request.args.get('offset', 0, type=int)
|
||||||
|
logs = db.activityRequest.get_recent_logs(limit=limit, offset=offset)
|
||||||
|
|
||||||
|
# Check if there are more logs to load
|
||||||
|
has_more = len(logs) == limit
|
||||||
|
|
||||||
|
return render_template('partials/activity_logs.html',
|
||||||
|
logs=logs,
|
||||||
|
offset=offset,
|
||||||
|
has_more=has_more)
|
||||||
@@ -192,8 +192,8 @@
|
|||||||
</svg>
|
</svg>
|
||||||
<span class="ml-3">Endpoints</span>
|
<span class="ml-3">Endpoints</span>
|
||||||
</a>
|
</a>
|
||||||
<a hx-get="{{ url_for('settings') }}" hx-push-url="true" hx-target="#container"
|
<a hx-get="{{ url_for('settings.settings') }}" hx-push-url="true" hx-target="#container"
|
||||||
class="text-base text-gray-900 font-normal rounded-lg hover:bg-gray-100 group transition duration-75 flex items-center p-2 cursor-pointer {{ is_selected_page(url_for('settings')) }} page-link"
|
class="text-base text-gray-900 font-normal rounded-lg hover:bg-gray-100 group transition duration-75 flex items-center p-2 cursor-pointer {{ is_selected_page(url_for('settings.settings')) }} page-link"
|
||||||
_="on click add .hidden to #sidebar then remove .ml-64 from #main
|
_="on click add .hidden to #sidebar then remove .ml-64 from #main
|
||||||
on htmx:afterRequest go to the top of the body">
|
on htmx:afterRequest go to the top of the body">
|
||||||
<svg class="w-6 h-6 text-gray-500 group-hover:text-gray-900 transition duration-75"
|
<svg class="w-6 h-6 text-gray-500 group-hover:text-gray-900 transition duration-75"
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
{% if has_more %}
|
{% if has_more %}
|
||||||
<tr id="load-more-row">
|
<tr id="load-more-row">
|
||||||
<td colspan="5" class="p-4 text-center">
|
<td colspan="5" class="p-4 text-center">
|
||||||
<button hx-get="/settings/activity_logs?offset={{ offset + limit }}"
|
<button hx-get="{{ url_for('settings.settings_activity_logs', offset=offset + limit) }}"
|
||||||
hx-target="#load-more-row" hx-swap="outerHTML"
|
hx-target="#load-more-row" hx-swap="outerHTML"
|
||||||
class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-cyan-700 bg-cyan-100 hover:bg-cyan-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-cyan-500 transition-colors">
|
class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-cyan-700 bg-cyan-100 hover:bg-cyan-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-cyan-500 transition-colors">
|
||||||
Load More...
|
Load More...
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<h3 class="text-xl font-bold text-gray-900">Activity Logs</h3>
|
<h3 class="text-xl font-bold text-gray-900">Activity Logs</h3>
|
||||||
<p class="text-sm text-gray-500">Review recent actions and administrative changes.</p>
|
<p class="text-sm text-gray-500">Review recent actions and administrative changes.</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="activity-logs-container" hx-get="/settings/activity_logs" hx-trigger="load">
|
<div id="activity-logs-container" hx-get="{{ url_for('settings.settings_activity_logs') }}" hx-trigger="load">
|
||||||
<div class="flex justify-center p-12">
|
<div class="flex justify-center p-12">
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<div class="animate-spin rounded-full h-10 w-10 border-b-2 border-cyan-600 mb-4"></div>
|
<div class="animate-spin rounded-full h-10 w-10 border-b-2 border-cyan-600 mb-4"></div>
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
<div class="border-b border-gray-200 mb-6 bg-gray-50 z-10">
|
<div class="border-b border-gray-200 mb-6 bg-gray-50 z-10">
|
||||||
<ul class="flex flex-wrap -mb-px text-sm font-medium text-center text-gray-500">
|
<ul class="flex flex-wrap -mb-px text-sm font-medium text-center text-gray-500">
|
||||||
<li class="mr-2">
|
<li class="mr-2">
|
||||||
<label for="radio-users" hx-get="/settings/tab/people" hx-target="#people-tab-content"
|
<label for="radio-users" hx-get="{{ url_for('settings.settings_people') }}"
|
||||||
hx-trigger="click"
|
hx-target="#people-tab-content" hx-trigger="click"
|
||||||
class="inline-flex items-center justify-center p-4 border-b-2 rounded-t-lg group cursor-pointer transition-colors
|
class="inline-flex items-center justify-center p-4 border-b-2 rounded-t-lg group cursor-pointer transition-colors
|
||||||
peer-checked/users:border-cyan-600 peer-checked/users:text-cyan-600 border-transparent hover:text-gray-700 hover:border-gray-300">
|
peer-checked/users:border-cyan-600 peer-checked/users:text-cyan-600 border-transparent hover:text-gray-700 hover:border-gray-300">
|
||||||
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
|
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
|
||||||
@@ -26,8 +26,8 @@
|
|||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li class="mr-2">
|
<li class="mr-2">
|
||||||
<label for="radio-exercises" hx-get="/settings/tab/exercises" hx-target="#exercises-tab-content"
|
<label for="radio-exercises" hx-get="{{ url_for('settings.settings_exercises') }}"
|
||||||
hx-trigger="click"
|
hx-target="#exercises-tab-content" hx-trigger="click"
|
||||||
class="inline-flex items-center justify-center p-4 border-b-2 rounded-t-lg group cursor-pointer transition-colors
|
class="inline-flex items-center justify-center p-4 border-b-2 rounded-t-lg group cursor-pointer transition-colors
|
||||||
peer-checked/exercises:border-cyan-600 peer-checked/exercises:text-cyan-600 border-transparent hover:text-gray-700 hover:border-gray-300">
|
peer-checked/exercises:border-cyan-600 peer-checked/exercises:text-cyan-600 border-transparent hover:text-gray-700 hover:border-gray-300">
|
||||||
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
|
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
|
||||||
@@ -41,8 +41,8 @@
|
|||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li class="mr-2">
|
<li class="mr-2">
|
||||||
<label for="radio-export" hx-get="/settings/tab/export" hx-target="#export-tab-content"
|
<label for="radio-export" hx-get="{{ url_for('settings.settings_export') }}"
|
||||||
hx-trigger="click"
|
hx-target="#export-tab-content" hx-trigger="click"
|
||||||
class="inline-flex items-center justify-center p-4 border-b-2 rounded-t-lg group cursor-pointer transition-colors
|
class="inline-flex items-center justify-center p-4 border-b-2 rounded-t-lg group cursor-pointer transition-colors
|
||||||
peer-checked/export:border-cyan-600 peer-checked/export:text-cyan-600 border-transparent hover:text-gray-700 hover:border-gray-300">
|
peer-checked/export:border-cyan-600 peer-checked/export:text-cyan-600 border-transparent hover:text-gray-700 hover:border-gray-300">
|
||||||
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
|
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
|
||||||
@@ -55,8 +55,8 @@
|
|||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li class="mr-2">
|
<li class="mr-2">
|
||||||
<label for="radio-activity" hx-get="/settings/tab/activity" hx-target="#activity-tab-content"
|
<label for="radio-activity" hx-get="{{ url_for('settings.settings_activity') }}"
|
||||||
hx-trigger="click"
|
hx-target="#activity-tab-content" hx-trigger="click"
|
||||||
class="inline-flex items-center justify-center p-4 border-b-2 rounded-t-lg group cursor-pointer transition-colors
|
class="inline-flex items-center justify-center p-4 border-b-2 rounded-t-lg group cursor-pointer transition-colors
|
||||||
peer-checked/activity:border-cyan-600 peer-checked/activity:text-cyan-600 border-transparent hover:text-gray-700 hover:border-gray-300">
|
peer-checked/activity:border-cyan-600 peer-checked/activity:text-cyan-600 border-transparent hover:text-gray-700 hover:border-gray-300">
|
||||||
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
|
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
|
||||||
@@ -72,8 +72,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Users Tab Content -->
|
<!-- Users Tab Content -->
|
||||||
<div class="hidden peer-checked/users:block" id="people-tab-content" hx-get="/settings/tab/people"
|
<div class="hidden peer-checked/users:block" id="people-tab-content"
|
||||||
hx-trigger="load">
|
hx-get="{{ url_for('settings.settings_people') }}" hx-trigger="load">
|
||||||
<div class="flex justify-center p-12">
|
<div class="flex justify-center p-12">
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<div class="animate-spin rounded-full h-10 w-10 border-b-2 border-cyan-600 mb-4"></div>
|
<div class="animate-spin rounded-full h-10 w-10 border-b-2 border-cyan-600 mb-4"></div>
|
||||||
|
|||||||
Reference in New Issue
Block a user