5c3c27e0af
Раздел «Справка» (категории/статьи/предложка), правки ad_connector и обновление тестов feed под обязательную 2FA. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
159 lines
5.4 KiB
Python
159 lines
5.4 KiB
Python
from __future__ import annotations
|
|
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.db.models import Count, Q
|
|
from django.http import HttpResponseRedirect
|
|
from django.shortcuts import get_object_or_404
|
|
from django.views.decorators.http import require_http_methods
|
|
|
|
from apps.help.models import HelpArticle, HelpCategory, HelpContribution
|
|
from apps.help.sanitize import plain_text_to_html
|
|
from core.utils.htmx import render_page
|
|
|
|
|
|
def _active_categories():
|
|
return (
|
|
HelpCategory.objects.filter(is_active=True)
|
|
.annotate(
|
|
article_count=Count(
|
|
'articles',
|
|
filter=Q(articles__is_published=True),
|
|
)
|
|
)
|
|
.order_by('sort_order', 'title')
|
|
)
|
|
|
|
|
|
def _published_articles():
|
|
return HelpArticle.objects.filter(is_published=True).select_related('category')
|
|
|
|
|
|
@login_required
|
|
def help_home_view(request):
|
|
q = (request.GET.get('q') or '').strip()
|
|
categories = list(_active_categories())
|
|
featured = list(
|
|
_published_articles()
|
|
.filter(is_featured=True)
|
|
.order_by('sort_order', 'title')[:12]
|
|
)
|
|
search_results = []
|
|
if q:
|
|
search_results = list(
|
|
_published_articles()
|
|
.filter(Q(title__icontains=q) | Q(body__icontains=q))
|
|
.order_by('sort_order', 'title')[:40]
|
|
)
|
|
my_contributions = list(
|
|
HelpContribution.objects.filter(author=request.user)
|
|
.select_related('category', 'article')
|
|
.order_by('-created_at')[:15]
|
|
)
|
|
return render_page(request, 'help.html', {
|
|
'help_categories': categories,
|
|
'help_featured': featured,
|
|
'help_query': q,
|
|
'help_search_results': search_results,
|
|
'help_my_contributions': my_contributions,
|
|
'help_message': request.GET.get('msg') or '',
|
|
})
|
|
|
|
|
|
@login_required
|
|
def help_category_view(request, slug):
|
|
category = get_object_or_404(HelpCategory, slug=slug, is_active=True)
|
|
articles = list(
|
|
_published_articles()
|
|
.filter(category=category)
|
|
.order_by('sort_order', 'title')
|
|
)
|
|
return render_page(request, 'help-category.html', {
|
|
'help_category': category,
|
|
'help_articles': articles,
|
|
})
|
|
|
|
|
|
@login_required
|
|
def help_article_view(request, slug):
|
|
article = get_object_or_404(
|
|
_published_articles(),
|
|
slug=slug,
|
|
)
|
|
related = list(
|
|
_published_articles()
|
|
.filter(category=article.category)
|
|
.exclude(pk=article.pk)
|
|
.order_by('sort_order', 'title')[:8]
|
|
)
|
|
return render_page(request, 'help-article.html', {
|
|
'help_article': article,
|
|
'help_related': related,
|
|
})
|
|
|
|
|
|
@login_required
|
|
@require_http_methods(['GET', 'POST'])
|
|
def help_contribute_view(request):
|
|
categories = list(HelpCategory.objects.filter(is_active=True).order_by('sort_order', 'title'))
|
|
article = None
|
|
article_id = request.GET.get('article') or request.POST.get('article_id') or ''
|
|
if article_id:
|
|
article = HelpArticle.objects.filter(pk=article_id, is_published=True).select_related('category').first()
|
|
|
|
errors: dict[str, str] = {}
|
|
preset_category = request.GET.get('category') or ''
|
|
form = {
|
|
'kind': HelpContribution.KIND_UPDATE if article else HelpContribution.KIND_CREATE,
|
|
'category_id': str(article.category_id) if article else str(preset_category),
|
|
'title': article.title if article else '',
|
|
'body': '',
|
|
'article_id': str(article.pk) if article else '',
|
|
}
|
|
|
|
if request.method == 'POST':
|
|
kind = request.POST.get('kind') or HelpContribution.KIND_CREATE
|
|
if kind not in (HelpContribution.KIND_CREATE, HelpContribution.KIND_UPDATE):
|
|
kind = HelpContribution.KIND_CREATE
|
|
category_id = request.POST.get('category_id') or ''
|
|
title = (request.POST.get('title') or '').strip()
|
|
raw_body = (request.POST.get('body') or '').strip()
|
|
form.update({
|
|
'kind': kind,
|
|
'category_id': category_id,
|
|
'title': title,
|
|
'body': raw_body,
|
|
'article_id': str(article.pk) if article else '',
|
|
})
|
|
|
|
category = HelpCategory.objects.filter(pk=category_id, is_active=True).first()
|
|
if not category:
|
|
errors['category_id'] = 'Выберите категорию.'
|
|
if not title:
|
|
errors['title'] = 'Укажите заголовок.'
|
|
if not raw_body:
|
|
errors['body'] = 'Добавьте текст статьи.'
|
|
if kind == HelpContribution.KIND_UPDATE and not article:
|
|
errors['article'] = 'Статья для правки не найдена.'
|
|
|
|
if not errors:
|
|
HelpContribution.objects.create(
|
|
kind=kind,
|
|
article=article if kind == HelpContribution.KIND_UPDATE else None,
|
|
category=category,
|
|
title=title[:250],
|
|
body=plain_text_to_html(raw_body),
|
|
author=request.user,
|
|
status=HelpContribution.STATUS_PENDING,
|
|
)
|
|
response = HttpResponseRedirect('/help/?msg=sent')
|
|
if request.headers.get('HX-Request'):
|
|
response['HX-Redirect'] = '/help/?msg=sent'
|
|
return response
|
|
|
|
return render_page(request, 'help-contribute.html', {
|
|
'help_categories': categories,
|
|
'help_article': article,
|
|
'help_form': form,
|
|
'help_errors': errors,
|
|
})
|