diff --git a/helpdesk/admin.py b/helpdesk/admin.py index 9d18007e..ad53346a 100644 --- a/helpdesk/admin.py +++ b/helpdesk/admin.py @@ -1,10 +1,13 @@ from django.contrib import admin from django.utils.translation import ugettext_lazy as _ -from helpdesk.models import Queue, Ticket, FollowUp, PreSetReply, KBCategory -from helpdesk.models import EscalationExclusion, EmailTemplate, KBItem +from helpdesk.models import Queue, Ticket, FollowUp, PreSetReply +from helpdesk.models import EscalationExclusion, EmailTemplate from helpdesk.models import TicketChange, KBIAttachment, FollowUpAttachment, IgnoreEmail from helpdesk.models import CustomField - +from helpdesk import settings as helpdesk_settings +if helpdesk_settings.HELPDESK_KB_ENABLED: + from helpdesk.models import KBCategory + from helpdesk.models import KBItem @admin.register(Queue) class QueueAdmin(admin.ModelAdmin): @@ -68,13 +71,18 @@ class FollowUpAdmin(admin.ModelAdmin): ticket_get_ticket_for_url.short_description = _('Slug') -@admin.register(KBItem) -class KBItemAdmin(admin.ModelAdmin): - list_display = ('category', 'title', 'last_updated', 'team', 'order', 'enabled') - inlines = [KBIAttachmentInline] - readonly_fields = ('voted_by', 'downvoted_by') +if helpdesk_settings.HELPDESK_KB_ENABLED: + @admin.register(KBItem) + class KBItemAdmin(admin.ModelAdmin): + list_display = ('category', 'title', 'last_updated', 'team', 'order', 'enabled') + inlines = [KBIAttachmentInline] + readonly_fields = ('voted_by', 'downvoted_by') - list_display_links = ('title',) + list_display_links = ('title',) + + @admin.register(KBCategory) + class KBCategoryAdmin(admin.ModelAdmin): + list_display = ('name', 'title', 'slug', 'public') @admin.register(CustomField) @@ -93,10 +101,5 @@ class IgnoreEmailAdmin(admin.ModelAdmin): list_display = ('name', 'queue_list', 'email_address', 'keep_in_mailbox') -@admin.register(KBCategory) -class KBCategoryAdmin(admin.ModelAdmin): - list_display = ('name', 'title', 'slug', 'public') - - admin.site.register(PreSetReply) admin.site.register(EscalationExclusion) diff --git a/helpdesk/forms.py b/helpdesk/forms.py index 377ad387..399b7e18 100644 --- a/helpdesk/forms.py +++ b/helpdesk/forms.py @@ -18,9 +18,13 @@ 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, KBItem) + CustomField, TicketCustomFieldValue, TicketDependency, UserSettings) from helpdesk import settings as helpdesk_settings + +if helpdesk_settings.HELPDESK_KB_ENABLED: + from helpdesk.models import (KBItem) + logger = logging.getLogger(__name__) User = get_user_model() @@ -231,13 +235,14 @@ class AbstractTicketForm(CustomFieldMixin, forms.Form): def __init__(self, kbcategory=None, *args, **kwargs): super().__init__(*args, **kwargs) - if kbcategory: - self.fields['kbitem'] = forms.ChoiceField( - widget=forms.Select(attrs={'class': 'form-control'}), - required=False, - label=_('Knowledge Base Item'), - choices=[(kbi.pk, kbi.title) for kbi in KBItem.objects.filter(category=kbcategory.pk, enabled=True)], - ) + if helpdesk_settings.HELPDESK_KB_ENABLED: + if kbcategory: + self.fields['kbitem'] = forms.ChoiceField( + widget=forms.Select(attrs={'class': 'form-control'}), + required=False, + label=_('Knowledge Base Item'), + choices=[(kbi.pk, kbi.title) for kbi in KBItem.objects.filter(category=kbcategory.pk, enabled=True)], + ) def _add_form_custom_fields(self, staff_only_filter=None): if staff_only_filter is None: diff --git a/helpdesk/models.py b/helpdesk/models.py index f8ffb8b1..df2bde7b 100644 --- a/helpdesk/models.py +++ b/helpdesk/models.py @@ -1275,166 +1275,166 @@ class EmailTemplate(models.Model): verbose_name = _('e-mail template') verbose_name_plural = _('e-mail templates') +if helpdesk_settings.HELPDESK_KB_ENABLED: + class KBCategory(models.Model): + """ + Lets help users help themselves: the Knowledge Base is a categorised + listing of questions & answers. + """ -class KBCategory(models.Model): - """ - Lets help users help themselves: the Knowledge Base is a categorised - listing of questions & answers. - """ + name = models.CharField( + _('Name of the category'), + max_length=100, + ) - name = models.CharField( - _('Name of the category'), - max_length=100, - ) + title = models.CharField( + _('Title on knowledgebase page'), + max_length=100, + ) - title = models.CharField( - _('Title on knowledgebase page'), - max_length=100, - ) + slug = models.SlugField( + _('Slug'), + ) - slug = models.SlugField( - _('Slug'), - ) + description = models.TextField( + _('Description'), + ) - description = models.TextField( - _('Description'), - ) + queue = models.ForeignKey( + Queue, + blank=True, + null=True, + on_delete=models.CASCADE, + verbose_name=_('Default queue when creating a ticket after viewing this category.'), + ) - queue = models.ForeignKey( - Queue, - blank=True, - null=True, - on_delete=models.CASCADE, - verbose_name=_('Default queue when creating a ticket after viewing this category.'), - ) + public = models.BooleanField( + default=True, + verbose_name=_("Is KBCategory publicly visible?") + ) - public = models.BooleanField( - default=True, - verbose_name=_("Is KBCategory publicly visible?") - ) + def __str__(self): + return '%s' % self.name - def __str__(self): - return '%s' % self.name + class Meta: + ordering = ('title',) + verbose_name = _('Knowledge base category') + verbose_name_plural = _('Knowledge base categories') - class Meta: - ordering = ('title',) - verbose_name = _('Knowledge base category') - verbose_name_plural = _('Knowledge base categories') - - def get_absolute_url(self): - from django.urls import reverse - return reverse('helpdesk:kb_category', kwargs={'slug': self.slug}) + def get_absolute_url(self): + from django.urls import reverse + return reverse('helpdesk:kb_category', kwargs={'slug': self.slug}) -class KBItem(models.Model): - """ - An item within the knowledgebase. Very straightforward question/answer - style system. - """ - voted_by = models.ManyToManyField( - settings.AUTH_USER_MODEL, - related_name='votes', - ) - downvoted_by = models.ManyToManyField( - settings.AUTH_USER_MODEL, - related_name='downvotes', - ) - category = models.ForeignKey( - KBCategory, - on_delete=models.CASCADE, - verbose_name=_('Category'), - ) + class KBItem(models.Model): + """ + An item within the knowledgebase. Very straightforward question/answer + style system. + """ + voted_by = models.ManyToManyField( + settings.AUTH_USER_MODEL, + related_name='votes', + ) + downvoted_by = models.ManyToManyField( + settings.AUTH_USER_MODEL, + related_name='downvotes', + ) + category = models.ForeignKey( + KBCategory, + on_delete=models.CASCADE, + verbose_name=_('Category'), + ) - title = models.CharField( - _('Title'), - max_length=100, - ) + title = models.CharField( + _('Title'), + max_length=100, + ) - question = models.TextField( - _('Question'), - ) + question = models.TextField( + _('Question'), + ) - answer = models.TextField( - _('Answer'), - ) + answer = models.TextField( + _('Answer'), + ) - votes = models.IntegerField( - _('Votes'), - help_text=_('Total number of votes cast for this item'), - default=0, - ) + votes = models.IntegerField( + _('Votes'), + help_text=_('Total number of votes cast for this item'), + default=0, + ) - recommendations = models.IntegerField( - _('Positive Votes'), - help_text=_('Number of votes for this item which were POSITIVE.'), - default=0, - ) + recommendations = models.IntegerField( + _('Positive Votes'), + help_text=_('Number of votes for this item which were POSITIVE.'), + default=0, + ) - last_updated = models.DateTimeField( - _('Last Updated'), - help_text=_('The date on which this question was most recently changed.'), - blank=True, - ) + last_updated = models.DateTimeField( + _('Last Updated'), + help_text=_('The date on which this question was most recently changed.'), + blank=True, + ) - team = models.ForeignKey( - helpdesk_settings.HELPDESK_TEAMS_MODEL, - on_delete=models.CASCADE, - verbose_name=_('Team'), - blank=True, - null=True, - ) + team = models.ForeignKey( + helpdesk_settings.HELPDESK_TEAMS_MODEL, + on_delete=models.CASCADE, + verbose_name=_('Team'), + blank=True, + null=True, + ) - order = models.PositiveIntegerField( - _('Order'), - blank=True, - null=True, - ) + order = models.PositiveIntegerField( + _('Order'), + blank=True, + null=True, + ) - enabled = models.BooleanField( - _('Enabled to display to users'), - default=True, - ) + enabled = models.BooleanField( + _('Enabled to display to users'), + default=True, + ) - def save(self, *args, **kwargs): - if not self.last_updated: - self.last_updated = timezone.now() - return super(KBItem, self).save(*args, **kwargs) + def save(self, *args, **kwargs): + if not self.last_updated: + self.last_updated = timezone.now() + return super(KBItem, self).save(*args, **kwargs) - def get_team(self): - return helpdesk_settings.HELPDESK_KBITEM_TEAM_GETTER(self) + def get_team(self): + return helpdesk_settings.HELPDESK_KBITEM_TEAM_GETTER(self) - def _score(self): - """ Return a score out of 10 or Unrated if no votes """ - if self.votes > 0: - return (self.recommendations / self.votes) * 10 - else: - return _('Unrated') - score = property(_score) + def _score(self): + """ Return a score out of 10 or Unrated if no votes """ + if self.votes > 0: + return (self.recommendations / self.votes) * 10 + else: + return _('Unrated') + score = property(_score) - def __str__(self): - return '%s: %s' % (self.category.title, self.title) + def __str__(self): + return '%s: %s' % (self.category.title, self.title) - class Meta: - ordering = ('order', 'title',) - verbose_name = _('Knowledge base item') - verbose_name_plural = _('Knowledge base items') + class Meta: + ordering = ('order', 'title',) + verbose_name = _('Knowledge base item') + verbose_name_plural = _('Knowledge base items') - def get_absolute_url(self): - from django.urls import reverse - return str(reverse('helpdesk:kb_category', args=(self.category.slug,))) + "?kbitem=" + str(self.pk) + def get_absolute_url(self): + from django.urls import reverse + return str(reverse('helpdesk:kb_category', args=(self.category.slug,))) + "?kbitem=" + str(self.pk) - def query_url(self): - from django.urls import reverse - return str(reverse('helpdesk:list')) + "?kbitem=" + str(self.pk) + def query_url(self): + from django.urls import reverse + return str(reverse('helpdesk:list')) + "?kbitem=" + str(self.pk) - def num_open_tickets(self): - return Ticket.objects.filter(kbitem=self, status__in=(1, 2)).count() + def num_open_tickets(self): + return Ticket.objects.filter(kbitem=self, status__in=(1, 2)).count() - def unassigned_tickets(self): - return Ticket.objects.filter(kbitem=self, status__in=(1, 2), assigned_to__isnull=True) + def unassigned_tickets(self): + return Ticket.objects.filter(kbitem=self, status__in=(1, 2), assigned_to__isnull=True) - def get_markdown(self): - return get_markdown(self.answer) + def get_markdown(self): + return get_markdown(self.answer) class SavedSearch(models.Model): diff --git a/helpdesk/urls.py b/helpdesk/urls.py index 6959a99b..e9df6bb2 100644 --- a/helpdesk/urls.py +++ b/helpdesk/urls.py @@ -14,7 +14,13 @@ from django.views.generic import TemplateView from helpdesk.decorators import helpdesk_staff_member_required, protect_view from helpdesk import settings as helpdesk_settings -from helpdesk.views import feeds, staff, public, kb, login +from helpdesk.views import feeds, staff, public, login +from helpdesk import settings as helpdesk_settings + + +if helpdesk_settings.HELPDESK_KB_ENABLED: + from helpdesk.views import kb + try: # TODO: why is it imported? due to some side-effect or by mistake? import helpdesk.tasks # NOQA diff --git a/helpdesk/views/staff.py b/helpdesk/views/staff.py index 462b3540..e4f74bbb 100644 --- a/helpdesk/views/staff.py +++ b/helpdesk/views/staff.py @@ -50,9 +50,12 @@ from helpdesk.lib import ( ) from helpdesk.models import ( Ticket, Queue, FollowUp, TicketChange, PreSetReply, FollowUpAttachment, SavedSearch, - IgnoreEmail, TicketCC, TicketDependency, UserSettings, KBItem, CustomField, TicketCustomFieldValue, + IgnoreEmail, TicketCC, TicketDependency, UserSettings, CustomField, TicketCustomFieldValue, ) from helpdesk import settings as helpdesk_settings +if helpdesk_settings.HELPDESK_KB_ENABLED: + from helpdesk.models import (KBItem) + import helpdesk.views.abstract_views as abstract_views from helpdesk.views.permissions import MustBeStaffMixin from ..lib import format_time_spent