support articles

This commit is contained in:
2025-06-24 09:43:31 +02:00
parent fed00ff2a0
commit 875e20304b
11 changed files with 1018 additions and 21 deletions

View File

@@ -253,4 +253,189 @@ def get_usage_stats():
stats = DocuPulseSettings.get_usage_stats()
return jsonify(stats)
except Exception as e:
return jsonify({'error': str(e)}), 500
return jsonify({'error': str(e)}), 500
@admin.route('/help-articles/<int:article_id>', methods=['PUT'])
@login_required
def update_help_article(article_id):
"""Update a help article"""
if not current_user.is_admin:
return jsonify({'error': 'Unauthorized'}), 403
try:
article = HelpArticle.query.get_or_404(article_id)
title = request.form.get('title')
category = request.form.get('category')
body = request.form.get('body')
order_index = int(request.form.get('order_index', 0))
is_published = request.form.get('is_published') == 'true'
if not title or not category or not body:
return jsonify({'error': 'Title, category, and body are required'}), 400
# Validate category
valid_categories = HelpArticle.get_categories().keys()
if category not in valid_categories:
return jsonify({'error': 'Invalid category'}), 400
article.title = title
article.category = category
article.body = body
article.order_index = order_index
article.is_published = is_published
article.updated_at = datetime.utcnow()
db.session.commit()
# Log the event
log_event(
event_type='help_article_update',
details={
'article_id': article.id,
'title': article.title,
'category': article.category,
'updated_by': f"{current_user.username} {current_user.last_name}"
},
user_id=current_user.id
)
db.session.commit()
return jsonify({'success': True, 'message': 'Article updated successfully'})
except Exception as e:
db.session.rollback()
return jsonify({'error': str(e)}), 500
@admin.route('/help-articles/<int:article_id>', methods=['DELETE'])
@login_required
def delete_help_article(article_id):
"""Delete a help article"""
if not current_user.is_admin:
return jsonify({'error': 'Unauthorized'}), 403
try:
article = HelpArticle.query.get_or_404(article_id)
# Log the event before deletion
log_event(
event_type='help_article_delete',
details={
'article_id': article.id,
'title': article.title,
'category': article.category,
'deleted_by': f"{current_user.username} {current_user.last_name}"
},
user_id=current_user.id
)
db.session.delete(article)
db.session.commit()
return jsonify({'success': True, 'message': 'Article deleted successfully'})
except Exception as e:
db.session.rollback()
return jsonify({'error': str(e)}), 500
# Help Articles API endpoints
@admin.route('/help-articles', methods=['GET'])
@login_required
def get_help_articles():
"""Get all help articles"""
if not current_user.is_admin:
return jsonify({'error': 'Unauthorized'}), 403
articles = HelpArticle.query.order_by(HelpArticle.category.asc(), HelpArticle.order_index.asc(), HelpArticle.created_at.desc()).all()
articles_data = []
for article in articles:
articles_data.append({
'id': article.id,
'title': article.title,
'category': article.category,
'body': article.body,
'created_at': article.created_at.isoformat() if article.created_at else None,
'updated_at': article.updated_at.isoformat() if article.updated_at else None,
'created_by': article.created_by,
'is_published': article.is_published,
'order_index': article.order_index
})
return jsonify({'articles': articles_data})
@admin.route('/help-articles', methods=['POST'])
@login_required
def create_help_article():
"""Create a new help article"""
if not current_user.is_admin:
return jsonify({'error': 'Unauthorized'}), 403
try:
title = request.form.get('title')
category = request.form.get('category')
body = request.form.get('body')
order_index = int(request.form.get('order_index', 0))
is_published = request.form.get('is_published') == 'true'
if not title or not category or not body:
return jsonify({'error': 'Title, category, and body are required'}), 400
# Validate category
valid_categories = HelpArticle.get_categories().keys()
if category not in valid_categories:
return jsonify({'error': 'Invalid category'}), 400
article = HelpArticle(
title=title,
category=category,
body=body,
order_index=order_index,
is_published=is_published,
created_by=current_user.id
)
db.session.add(article)
db.session.commit()
# Log the event
log_event(
event_type='help_article_create',
details={
'article_id': article.id,
'title': article.title,
'category': article.category,
'created_by': f"{current_user.username} {current_user.last_name}"
},
user_id=current_user.id
)
db.session.commit()
return jsonify({'success': True, 'message': 'Article created successfully', 'article_id': article.id})
except Exception as e:
db.session.rollback()
return jsonify({'error': str(e)}), 500
@admin.route('/help-articles/<int:article_id>', methods=['GET'])
@login_required
def get_help_article(article_id):
"""Get a specific help article"""
if not current_user.is_admin:
return jsonify({'error': 'Unauthorized'}), 403
article = HelpArticle.query.get_or_404(article_id)
article_data = {
'id': article.id,
'title': article.title,
'category': article.category,
'body': article.body,
'created_at': article.created_at.isoformat() if article.created_at else None,
'updated_at': article.updated_at.isoformat() if article.updated_at else None,
'created_by': article.created_by,
'is_published': article.is_published,
'order_index': article.order_index
}
return jsonify({'article': article_data})

View File

@@ -2,9 +2,11 @@ from flask import Blueprint, jsonify, request, current_app, make_response, flash
from functools import wraps
from models import (
KeyValueSettings, User, Room, Conversation, RoomFile,
SiteSettings, DocuPulseSettings, Event, Mail, ManagementAPIKey, PasswordSetupToken, PasswordResetToken
SiteSettings, DocuPulseSettings, Event, Mail, ManagementAPIKey, PasswordSetupToken, PasswordResetToken,
HelpArticle
)
from extensions import db, csrf
from utils import log_event
from datetime import datetime, timedelta
import os
import jwt
@@ -590,4 +592,5 @@ def get_version_info(current_user):
'git_commit': 'unknown',
'git_branch': 'unknown',
'deployed_at': 'unknown'
}), 500
}), 500

View File

@@ -1,5 +1,5 @@
from flask import Blueprint, render_template, redirect, url_for
from models import SiteSettings
from flask import Blueprint, render_template, redirect, url_for, request
from models import SiteSettings, HelpArticle
import os
def init_public_routes(public_bp):
@@ -38,6 +38,30 @@ def init_public_routes(public_bp):
"""Help Center page"""
return render_template('public/help.html')
@public_bp.route('/help/articles')
def help_articles():
"""Display help articles by category"""
category = request.args.get('category', '')
# Get all published articles grouped by category
all_articles = HelpArticle.get_all_published()
categories = HelpArticle.get_categories()
# If a specific category is requested, filter to that category
if category and category in categories:
articles = HelpArticle.get_articles_by_category(category)
category_name = categories[category]
else:
articles = []
category_name = None
return render_template('public/help_articles.html',
articles=articles,
all_articles=all_articles,
categories=categories,
current_category=category,
category_name=category_name)
@public_bp.route('/contact')
def contact():
"""Contact page"""