Redo KB categories as accordion view

This commit is contained in:
Timothy Hobbs 2020-01-07 13:33:06 +01:00
parent c95b24780e
commit 7fe6444f8f
7 changed files with 65 additions and 88 deletions

View File

@ -18,7 +18,7 @@ from django.utils import timezone
from helpdesk.lib import safe_template_context, process_attachments
from helpdesk.models import (Ticket, Queue, FollowUp, IgnoreEmail, TicketCC,
CustomField, TicketCustomFieldValue, TicketDependency, UserSettings)
CustomField, TicketCustomFieldValue, TicketDependency, UserSettings, KBItem)
from helpdesk import settings as helpdesk_settings
User = get_user_model()
@ -197,7 +197,10 @@ class AbstractTicketForm(CustomFieldMixin, forms.Form):
return Queue.objects.get(id=int(self.cleaned_data['queue']))
def _create_ticket(self):
queue = self._get_queue()
queue = Queue.objects.get(id=int(self.cleaned_data['queue']))
kbitem = None
if 'kbitem' in self.cleaned_data:
kbitem = KBItem.objects.get(id=int(self.cleaned_data['kbitem']))
ticket = Ticket(title=self.cleaned_data['title'],
submitter_email=self.cleaned_data['submitter_email'],
@ -207,6 +210,7 @@ class AbstractTicketForm(CustomFieldMixin, forms.Form):
description=self.cleaned_data['body'],
priority=self.cleaned_data['priority'],
due_date=self.cleaned_data['due_date'],
kbitem=kbitem,
)
return ticket, queue
@ -337,13 +341,22 @@ class PublicTicketForm(AbstractTicketForm):
help_text=_('We will e-mail you when your ticket is updated.'),
)
def __init__(self, hidden_fields=(), readonly_fields=(), *args, **kwargs):
def __init__(self, hidden_fields=(), readonly_fields=(), kbcategory=None, *args, **kwargs):
"""
Add any (non-staff) custom fields that are defined to the form
"""
super(PublicTicketForm, self).__init__(*args, **kwargs)
self._add_form_custom_fields(False)
if kbcategory:
self.fields['kbitem'] = forms.ChoiceField(
widget=forms.Select(attrs={'class': 'form-control'}),
required=False,
label=_('Knowedge Base Item'),
choices=[(kbi.pk, kbi.title) for kbi in KBItem.objects.filter(category=kbcategory.pk)],
)
field_hide_table = {
'queue': 'HELPDESK_PUBLIC_TICKET_QUEUE',
'priority': 'HELPDESK_PUBLIC_TICKET_PRIORITY',

View File

@ -559,6 +559,14 @@ class Ticket(models.Model):
default=mk_secret,
)
kbitem = models.ForeignKey(
"KBItem",
blank=True,
null=True,
on_delete=models.CASCADE,
verbose_name=_('Knowledge base item the user was viewing when they created this ticket.'),
)
@property
def time_spent(self):
"""Return back total time spent on the ticket. This is calculated value
@ -1310,7 +1318,7 @@ class KBItem(models.Model):
def get_absolute_url(self):
from django.urls import reverse
return reverse('helpdesk:kb_item', args=(self.id,))
return str(reverse('helpdesk:kb_category', args=(self.category.slug,)))+"?kbitem="+str(self.pk)
def get_markdown(self):
return get_markdown(self.answer)

View File

@ -19,29 +19,37 @@
<p>{{ category.description }}</p>
</div>
</div>
<div id="accordion">
{% for item in items %}
{% cycle 'one' 'two' 'three' as itemnumperrow silent %}
{% ifequal itemnumperrow 'one' %}<div class="card-deck">{% endifequal %}
<div class="card">
<div class="card-header">
<h5 class="card-title">{{ item.title }}</h5>
</div>
<div class="card-body">
<p class="card-text">{{ item.question }}</p>
<p class="card-text">
{% blocktrans with item.get_absolute_url as url %}<a href='{{ url }}' class="btn btn-primary"> Go to answer <i class="fa fa-share"></i></a>{% endblocktrans %}
</p>
<div class="well well-sm">
<p>{% trans 'Rating' %}: {{ item.score }}</p>
<p>{% trans 'Last Update' %}: {{ item.last_updated|naturaltime }}</p>
<div class="card mb-3">
<button class="btn btn-link" data-toggle="collapse" data-target="#collapse{{item.id}}" aria-expanded="true" aria-controls="collapse{{item.id}}">
<div class="card-header" id="header{{item.id}}">
<h5 class="mb-0">
{{ item.title }}
</h5>
</div>
</button>
<div id="collapse{{item.id}}" class="collapse {% if item.id == selected_item %}show{% endif %}" aria-labelledby="header{{item.id}}" data-parent="#accordion">
<div class="card-body">
<p class="card-text">{{ item.question }}</p>
<p>{{ item.get_markdown }}</p>
<div class="row">
{% if request.user.pk %}
<div>
<a href='{% url "helpdesk:kb_vote" item.pk %}?vote=up'><button type="button" class="btn btn-success btn-circle btn-xl"><i class="fa fa-thumbs-up fa-lg"></i></button></a>
</div>
<div>
<a href='{% url "helpdesk:kb_vote" item.pk %}?vote=down'><button type="button" class="btn btn-danger btn-circle btn-xl"><i class="fa fa-thumbs-down fa-lg"></i></button></a>
</div>
{% blocktrans with recommendations=item.recommendations votes=item.votes %}{{ recommendations }} people found this answer useful of {{votes}}. {% endblocktrans %}
{% endif %}
</div>
</p>
</div>
</div>
</div>
{% ifequal itemnumperrow 'three' %}</div>{% endifequal %}
{% endfor %}
{% ifnotequal itemnumperrow 'three' %}</div>{% endifnotequal %}
</div>
{% if category.queue %}
<a href='{% url 'helpdesk:submit' %}?queue={{category.queue.pk}};_readonly_fields_=queue'><button type="button" class="btn btn-success btn-circle btn-xl float-right"><i class="fa fa-envelope fa-lg"></i> {% trans 'Get help with this topic' %}</button></a>
{% endif %}

View File

@ -1,51 +0,0 @@
{% extends "helpdesk/public_base.html" %}{% load i18n %}
{% block helpdesk_breadcrumb %}
<li class="breadcrumb-item">
<a href="{% url 'helpdesk:kb_index' %}">{% trans "Knowledgebase" %}</a>
</li>
<li class="breadcrumb-item">
<a href="{{ category.get_absolute_url }}">{% blocktrans with category.title as kbcat %}{{ kbcat }}{% endblocktrans %}</a>
</li>
<li class="breadcrumb-item active">Overview</li>
{% endblock %}
{% block helpdesk_body %}
<h2>{% trans 'Knowledgebase' %}: {% blocktrans with item.title as item %}{{ item }}{% endblocktrans %}</h2>
<div class="card mb-3">
<div class="card-header">
<i class="fas fa-question-circle"></i>
{{ item.question }}
</div>
<div class="card-body">
<p>{{ item.get_markdown }}</p>
</div>
<div class="card-footer">
<div class="row">
<div class="col-lg-2">
<p>{% trans "Did you find this article useful?" %}</p>
<div class="row">
<div class="col-lg-6">
<a href='vote/?vote=up'><button type="button" class="btn btn-success btn-circle btn-xl"><i class="fa fa-thumbs-up fa-lg"></i></button></a>
</div>
<div class="col-lg-6">
<a href='vote/?vote=down'><button type="button" class="btn btn-danger btn-circle btn-xl"><i class="fa fa-thumbs-down fa-lg"></i></button></a>
</div>
</div>
</div>
<div class="col-lg-10">
<p>{% trans "The results of voting by other readers of this article are below:" %}</p>
<ul>
<li>{% blocktrans with item.recommendations as recommendations %}Recommendations: {{ recommendations }}{% endblocktrans %}</li>
<li>{% blocktrans with item.votes as votes %}Votes: {{ votes }}{% endblocktrans %}</li>
<li>{% blocktrans with item.score as score %}Overall Rating: {{ score }}{% endblocktrans %}</li>
</ul>
</div>
</div>
</div>
</div>
<p>{% blocktrans with item.category.title as category_title and item.category.get_absolute_url as category_url %}View <a href='{{ category_url }}'>other <em>{{ category_title }}</em> articles</a>, or continue <a href='../'>viewing other knowledgebase articles</a>.{% endblocktrans %}</p>
{% endblock %}

View File

@ -232,10 +232,6 @@ if helpdesk_settings.HELPDESK_KB_ENABLED:
kb.index,
name='kb_index'),
url(r'^kb/(?P<item>[0-9]+)/$',
kb.item,
name='kb_item'),
url(r'^kb/(?P<item>[0-9]+)/vote/$',
kb.vote,
name='kb_vote'),

View File

@ -27,18 +27,15 @@ def index(request):
def category(request, slug):
category = get_object_or_404(KBCategory, slug__iexact=slug)
items = category.kbitem_set.all()
selected_item = request.GET.get('kbitem', None)
try:
selected_item = int(selected_item)
except ValueError:
pass
return render(request, 'helpdesk/kb_category.html', {
'category': category,
'items': items,
'helpdesk_settings': helpdesk_settings,
})
def item(request, item):
item = get_object_or_404(KBItem, pk=item)
return render(request, 'helpdesk/kb_item.html', {
'category': item.category,
'item': item,
'selected_item': selected_item,
'helpdesk_settings': helpdesk_settings,
})

View File

@ -21,7 +21,7 @@ from helpdesk.decorators import protect_view, is_helpdesk_staff
import helpdesk.views.staff as staff
from helpdesk.forms import PublicTicketForm
from helpdesk.lib import text_is_spam
from helpdesk.models import CustomField, Ticket, Queue, UserSettings, KBCategory
from helpdesk.models import CustomField, Ticket, Queue, UserSettings, KBCategory, KBItem
def create_ticket(request, *args, **kwargs):
@ -82,7 +82,7 @@ class BaseCreateTicketView(FormView):
if request.user.is_authenticated and request.user.email:
initial_data['submitter_email'] = request.user.email
query_param_fields = ['submitter_email', 'title', 'body', 'queue']
query_param_fields = ['submitter_email', 'title', 'body', 'queue', 'kbitem']
custom_fields = ["custom_%s" % f.name for f in CustomField.objects.filter(staff_only=False)]
query_param_fields += custom_fields
for qpf in query_param_fields:
@ -93,6 +93,12 @@ class BaseCreateTicketView(FormView):
kwargs = super().get_form_kwargs(*args, **kwargs)
kwargs['hidden_fields'] = self.request.GET.get('_hide_fields_', '').split(',')
kwargs['readonly_fields'] = self.request.GET.get('_readonly_fields_', '').split(',')
kbitem = self.request.GET.get('kbitem', None)
if kbitem:
try:
kwargs['kbcategory'] = KBItem.objects.get(pk=int(kbitem))
except (ValueError, KBItem.DoesNotExist):
pass
return kwargs
def form_valid(self, form):