Add recent conversations

This commit is contained in:
Minecon724 2025-04-04 08:29:13 +02:00
commit 2cc5bc7765
Signed by: Minecon724
GPG key ID: A02E6E67AB961189
4 changed files with 290 additions and 11 deletions

View file

@ -1,9 +1,10 @@
from flask import request, jsonify, render_template, redirect, url_for, flash, session
from flask import request, jsonify, render_template, redirect, url_for, flash, session, make_response
from . import app, db, limiter, csrf, webhooks
from .webhooks import WebhookError
from .models import Inquiry, Message, Settings, Admin
import os
from datetime import datetime, timedelta
import json
from datetime import datetime, timedelta, timezone
# Import admin routes (these will be registered with the app)
from . import admin_routes
@ -13,7 +14,50 @@ from .admin_routes import is_admin
@app.route('/', methods=['GET'])
def index():
return render_template('create_inquiry.html')
# Get recent inquiries from cookie
recent_inquiries = []
read_status = {}
if request.cookies.get('recent_inquiries'):
try:
inquiry_ids = json.loads(request.cookies.get('recent_inquiries'))
recent_inquiries = Inquiry.query.filter(Inquiry.id.in_(inquiry_ids)).all()
# Get read status for each inquiry
if request.cookies.get('read_messages'):
read_status = json.loads(request.cookies.get('read_messages'))
except:
# If there's an error parsing the cookie, just ignore it
pass
# Create a list to store inquiries with their data
inquiries_with_data = []
for inquiry_id in (inquiry_ids if 'inquiry_ids' in locals() else []):
for inquiry in recent_inquiries:
if inquiry.id == inquiry_id:
# Get last message for the inquiry
last_message = Message.query.filter_by(inquiry_id=inquiry.id).order_by(Message.message_number.desc()).first()
# Check if there are unread messages
is_unread = False
if last_message:
last_read = read_status.get(inquiry.id, 0)
if last_message.message_number > last_read and last_message.is_admin:
is_unread = True
inquiries_with_data.append({
'inquiry': inquiry,
'last_message': last_message,
'is_unread': is_unread,
'position': inquiry_ids.index(inquiry.id) # Keep track of original position
})
break
# Sort inquiries - unread first, then by original position (recency)
inquiries_with_data.sort(key=lambda x: (0 if x['is_unread'] else 1, x['position']))
return render_template('create_inquiry.html', recent_inquiries=inquiries_with_data)
@app.route('/', methods=['POST'])
@limiter.limit("5 per hour")
@ -40,7 +84,8 @@ def create_inquiry():
webhooks.inquiry_created(new_inquiry.id, initial_message)
except WebhookError as e:
app.logger.error(f"Error sending webhook for new inquiry: {str(e)}")
# Add to recent inquiries cookie
return redirect(url_for('inquiry', inquiry_id=new_inquiry.id))
@app.route('/inquiry/<inquiry_id>', methods=['GET', 'POST'])
@ -48,7 +93,7 @@ def create_inquiry():
def inquiry(inquiry_id):
inquiry = Inquiry.query.get_or_404(inquiry_id)
is_admin_user = is_admin()
if request.method == 'POST':
# Handle closed inquiry differently for admin vs non-admin
if inquiry.is_closed:
@ -81,10 +126,57 @@ def inquiry(inquiry_id):
except WebhookError as e:
app.logger.error(f"Error sending webhook for message: {str(e)}")
return redirect(url_for('inquiry', inquiry_id=inquiry_id))
response = redirect(url_for('inquiry', inquiry_id=inquiry_id))
return add_inquiry_to_cookie(response, inquiry_id) if not is_admin_user else response
messages = Message.query.filter_by(inquiry_id=inquiry_id).order_by(Message.message_number).all()
return render_template('inquiry.html', inquiry=inquiry, messages=messages)
# Update the recent inquiries cookie when viewing an inquiry
response = make_response(render_template('inquiry.html', inquiry=inquiry, messages=messages))
if not is_admin_user: # Only track inquiries for regular users, not admins
response = add_inquiry_to_cookie(response, inquiry_id)
# Mark all messages in this inquiry as read
if messages:
last_message_number = messages[-1].message_number
read_status = {}
if request.cookies.get('read_messages'):
try:
read_status = json.loads(request.cookies.get('read_messages'))
except:
pass
# Store directly as inquiry_id: last_read_message_number mapping
read_status[inquiry_id] = last_message_number
expires = datetime.now(timezone.utc) + timedelta(days=30)
response.set_cookie('read_messages', json.dumps(read_status), expires=expires, httponly=True)
return response
# Helper function to add an inquiry to the recent inquiries cookie
def add_inquiry_to_cookie(response, inquiry_id):
recent_inquiries = []
if request.cookies.get('recent_inquiries'):
try:
recent_inquiries = json.loads(request.cookies.get('recent_inquiries'))
except:
recent_inquiries = []
# Add the current inquiry to the front of the list if it's not already there
if inquiry_id in recent_inquiries:
recent_inquiries.remove(inquiry_id)
recent_inquiries.insert(0, inquiry_id)
# Keep only the 5 most recent inquiries
recent_inquiries = recent_inquiries[:5]
# Set the cookie to expire in 30 days
expires = datetime.now(timezone.utc) + timedelta(days=30)
# Set the cookie
response.set_cookie('recent_inquiries', json.dumps(recent_inquiries), expires=expires, httponly=True)
return response
@app.route('/inquiry/<inquiry_id>/delete', methods=['POST'])
@limiter.limit("10 per hour", deduct_when=lambda response: response.status_code != 200)
@ -181,4 +273,18 @@ def reopen_inquiry(inquiry_id):
if referrer and 'admin/dashboard' in referrer:
return redirect(url_for('admin_dashboard'))
else:
return redirect(url_for('inquiry', inquiry_id=inquiry_id))
return redirect(url_for('inquiry', inquiry_id=inquiry_id))
@app.route('/forget_inquiries', methods=['POST'])
def forget_inquiries():
# Create a response that redirects to the index page
response = redirect(url_for('index'))
# Clear the recent inquiries cookie by setting it to empty and expiring immediately
response.set_cookie('recent_inquiries', '', expires=0)
# Also clear the read messages status cookie
response.set_cookie('read_messages', '', expires=0)
flash('Your recent conversations have been forgotten.')
return response

View file

@ -142,4 +142,140 @@ th {
.btn-primary:hover {
background-color: #2d6c30;
text-decoration: none;
}
}
/* Recent Inquiries Styles */
.recent-inquiries {
margin-top: 2rem;
padding-top: 1.5rem;
border-top: 1px solid #444;
}
.recent-header {
display: flex;
align-items: center;
margin-bottom: 1rem;
}
.recent-header h3 {
margin: 0;
color: #bbb;
}
.recent-header form {
margin: 0;
}
.forget-button {
background-color: #8c3b3b;
color: white;
padding: 0.4rem 0.8rem;
font-size: 0.9rem;
margin-left: 1rem;
}
.forget-button:hover {
background-color: #a04343;
}
.inquiry-list {
list-style: none;
padding: 0;
margin: 0;
}
.inquiry-list li {
margin-bottom: 0.8rem;
}
.inquiry-list a {
text-decoration: none;
}
.inquiry-list a:hover {
text-decoration: none;
}
.inquiry-item {
padding: 1rem;
background-color: #333;
border-radius: 4px;
transition: background-color 0.2s ease;
border-left: 3px solid transparent;
}
.inquiry-item:hover {
background-color: #3a3a3a;
}
/* Unread inquiry styling */
.inquiry-item.unread {
border-left: 3px solid #3b8c3e;
background-color: #383f38;
}
.inquiry-item.unread:hover {
background-color: #404a40;
}
.inquiry-header {
display: flex;
align-items: center;
margin-bottom: 0.5rem;
}
.inquiry-id {
font-weight: bold;
display: inline-block;
margin-right: 0.5rem;
}
.inquiry-status {
font-size: 0.8rem;
padding: 2px 6px;
border-radius: 3px;
display: inline-block;
}
.inquiry-status.open {
background-color: #3b8c3e;
color: white;
}
.inquiry-status.closed {
background-color: #8c3b3b;
color: white;
}
.unread-badge {
margin-left: auto;
background-color: #3b8c3e;
color: white;
padding: 2px 8px;
border-radius: 10px;
font-size: 0.75rem;
font-weight: bold;
animation: pulse 2s infinite;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(59, 140, 62, 0.4);
}
70% {
box-shadow: 0 0 0 6px rgba(59, 140, 62, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(59, 140, 62, 0);
}
}
.inquiry-message {
margin: 0.4rem 0;
color: #bbb;
font-size: 0.9rem;
}
h2, h3 {
padding-left: 1rem;
}

View file

@ -19,4 +19,41 @@
<button type="submit">Create New Inquiry</button>
</form>
</div>
{% if recent_inquiries %}
<div class="recent-inquiries">
<div class="recent-header">
<h3>Your Recent Conversations</h3>
<form method="POST" action="{{ url_for('forget_inquiries') }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<button type="submit" class="forget-button">Forget All</button>
</form>
</div>
<ul class="inquiry-list">
{% for item in recent_inquiries %}
<li>
<a href="{{ url_for('inquiry', inquiry_id=item.inquiry.id) }}">
<div class="inquiry-item {% if item.is_unread %}unread{% endif %}">
<div class="inquiry-header">
<span class="inquiry-id">Inquiry #{{ item.inquiry.id[:8] }}</span>
<span class="inquiry-status {% if item.inquiry.is_closed %}closed{% else %}open{% endif %}">
{% if item.inquiry.is_closed %}Closed{% else %}Open{% endif %}
</span>
{% if item.is_unread %}
<span class="unread-badge">New Message</span>
{% endif %}
</div>
{% if item.last_message %}
<p class="inquiry-message">
<strong>{% if item.last_message.is_admin %}Admin:{% else %}You:{% endif %}</strong>
{{ item.last_message.content[:50] }}{% if item.last_message.content|length > 50 %}...{% endif %}
</p>
{% endif %}
</div>
</a>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% endblock %}

View file

@ -1,10 +1,10 @@
{% extends "base.html" %}
{% block title %}Inquiry #{{ inquiry.id[:6] }}{% endblock %}
{% block title %}Inquiry #{{ inquiry.id[:8] }}{% endblock %}
{% block header %}
<h2>
Inquiry #{{ inquiry.id[:6] }}
Inquiry #{{ inquiry.id[:8] }}
{% if inquiry.is_closed %}
<span style="color: #6c757d; font-size: 0.9rem; padding: 0.3rem 0.6rem; background-color: #e9ecef; border-radius: 0.25rem; margin-left: 0.5rem;">CLOSED</span>