Christian Kniep
add settings and UI/UX improvements
2e18bf2
{% extends "base.html" %}
{% block title %}Settings - PrepMate{% endblock %}
{% block head %}
<style>
.deprecated-warning {
background-color: #fff3cd;
border-left: 4px solid #ffc107;
padding: 12px 16px;
margin-bottom: 20px;
border-radius: 4px;
}
.deprecated-warning .bi {
font-size: 1.2em;
margin-right: 8px;
}
.model-info {
font-size: 0.875rem;
color: #6c757d;
margin-top: 4px;
}
.settings-card {
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
</style>
{% endblock %}
{% block content %}
<div class="container mt-4">
<div class="row">
<div class="col-lg-8 mx-auto">
<h1 class="mb-4">
<i class="bi bi-gear"></i> Settings
</h1>
{% if settings %}
<div class="card settings-card">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">
<i class="bi bi-cpu"></i> AI Model Selection
</h5>
</div>
<div class="card-body">
<p class="text-muted">
Configure which OpenAI models are used for different operations.
Your selections will be used for all future AI interactions.
</p>
<form method="POST" action="{{ url_for('settings.update_settings') }}">
<!-- Reply Generation Model -->
<div class="mb-4">
<label for="reply_generation_model" class="form-label fw-bold">
<i class="bi bi-chat-dots"></i> Reply Generation Model
</label>
<select
class="form-select"
id="reply_generation_model"
name="reply_generation_model"
required
>
{% for model in settings.valid_models %}
<option value="{{ model }}"
{% if model == settings.reply_generation_model %}selected{% endif %}>
{{ model }}
</option>
{% endfor %}
</select>
<div class="model-info">
Used when generating AI responses to your questions and messages.
</div>
</div>
<!-- Last Updated -->
<div class="mb-3">
<small class="text-muted">
<i class="bi bi-clock"></i> Last updated: {{ settings.updated_at }}
</small>
</div>
<!-- Submit Button -->
<div class="d-grid gap-2">
<button type="submit" class="btn btn-primary">
<i class="bi bi-check-circle"></i> Save Settings
</button>
</div>
</form>
</div>
</div>
<!-- Available Models Reference -->
<div class="card mt-4">
<div class="card-header">
<h6 class="mb-0">
<i class="bi bi-info-circle"></i> Available Model
</h6>
</div>
<div class="card-body">
<p class="mb-0"><strong>gpt-4.1-mini:</strong> Cost-effective GPT-4 variant</p>
</div>
</div>
<!-- Response Template Editor (US2) -->
<div class="card settings-card mt-4">
<div class="card-header bg-success text-white">
<h5 class="mb-0">
<i class="bi bi-file-text"></i> Response Template
</h5>
</div>
<div class="card-body">
<p class="text-muted">
Customize how AI responses are structured. Templates use Go template syntax with variables like {% raw %}{{.UserMessage}}{% endraw %}, {% raw %}{{.SessionProfile}}{% endraw %}, etc.
</p>
<form method="POST" action="{{ url_for('settings.create_template') }}" id="template-form">
<!-- Template Content Textarea -->
<div class="mb-3">
<label for="template_content" class="form-label fw-bold">
<i class="bi bi-code-square"></i> Template Content
</label>
<textarea
class="form-control font-monospace"
id="template_content"
name="template_content"
rows="15"
maxlength="10000"
required
style="font-size: 0.875rem;"
>{% if active_template %}{{ active_template.template_content }}{% endif %}</textarea>
<div class="form-text">
<span id="char-count">0</span> / 10000 characters
</div>
</div>
<!-- Version History Dropdown -->
{% if template_versions and template_versions|length > 0 %}
<div class="mb-3">
<label for="version_selector" class="form-label fw-bold">
<i class="bi bi-clock-history"></i> Version History
</label>
<select class="form-select" id="version_selector">
{% for version in template_versions %}
<option
value="{{ version.version_id }}"
data-content="{{ version.template_content }}"
{% if version.is_active %}selected{% endif %}
>
{{ version.created_at }} {% if version.is_active %}(Active){% endif %}
</option>
{% endfor %}
</select>
<div class="form-text">
Select a previous version to view or activate it.
</div>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-success">
<i class="bi bi-save"></i> Save New Version
</button>
<button type="button" class="btn btn-outline-primary" id="activate-btn">
<i class="bi bi-check-circle"></i> Activate Selected Version
</button>
</div>
{% else %}
<div class="mb-3">
<p class="text-muted">
<i class="bi bi-info-circle"></i> No version history yet. Save your first template version above.
</p>
</div>
<button type="submit" class="btn btn-success">
<i class="bi bi-save"></i> Save New Version
</button>
{% endif %}
</form>
</div>
</div>
{% else %}
<div class="alert alert-warning">
<i class="bi bi-exclamation-triangle"></i>
Unable to load settings. Please try again later.
</div>
{% endif %}
</div>
</div>
</div>
<script>
// Character counter
const templateTextarea = document.getElementById('template_content');
const charCount = document.getElementById('char-count');
function updateCharCount() {
if (templateTextarea && charCount) {
charCount.textContent = templateTextarea.value.length;
}
}
if (templateTextarea) {
templateTextarea.addEventListener('input', updateCharCount);
updateCharCount(); // Initial count
}
// Version selector - load template content when selecting a version
const versionSelector = document.getElementById('version_selector');
if (versionSelector) {
versionSelector.addEventListener('change', function() {
const selectedOption = this.options[this.selectedIndex];
const content = selectedOption.getAttribute('data-content');
if (content && templateTextarea) {
templateTextarea.value = content;
updateCharCount();
}
});
}
// Activate selected version button
const activateBtn = document.getElementById('activate-btn');
if (activateBtn) {
activateBtn.addEventListener('click', function() {
if (!versionSelector) return;
const versionId = versionSelector.value;
if (!versionId) {
alert('Please select a version to activate');
return;
}
// Send POST request to activate endpoint
fetch(`{{ url_for('settings.activate_template', version_id='__VERSION_ID__') }}`.replace('__VERSION_ID__', versionId), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
window.location.reload();
} else {
alert('Error activating template: ' + (data.error || 'Unknown error'));
}
})
.catch(error => {
console.error('Error:', error);
alert('Error activating template. Please try again.');
});
});
}
</script>
{% endblock %}