stash
This commit is contained in:
parent
ecbe989f43
commit
38d8b35084
3 changed files with 63 additions and 7 deletions
|
@ -1,4 +1,5 @@
|
|||
import logging
|
||||
from base64 import b64decode
|
||||
|
||||
from django.urls import re_path
|
||||
from django.contrib.auth.decorators import permission_required
|
||||
|
@ -15,7 +16,7 @@ from mail.models import Email
|
|||
from mail.protocol import send_smtp, make_reply, collect_references
|
||||
from notify_sessions.models import SystemEvent
|
||||
from tickets.models import IssueThread, Comment, STATE_CHOICES, ShippingVoucher
|
||||
from tickets.serializers import IssueSerializer, CommentSerializer, ShippingVoucherSerializer
|
||||
from tickets.serializers import IssueSerializer, CommentSerializer, ShippingVoucherSerializer, SearchResultSerializer
|
||||
|
||||
|
||||
class IssueViewSet(viewsets.ModelViewSet):
|
||||
|
@ -61,7 +62,7 @@ def reply(request, pk):
|
|||
@api_view(['POST'])
|
||||
@permission_classes([IsAuthenticated])
|
||||
@permission_required('tickets.add_issuethread_manual', raise_exception=True)
|
||||
def manual_ticket(request):
|
||||
def manual_ticket(request, event_slug):
|
||||
if 'name' not in request.data:
|
||||
return Response({'status': 'error', 'message': 'missing name'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
if 'sender' not in request.data:
|
||||
|
@ -122,14 +123,39 @@ def add_comment(request, pk):
|
|||
return Response(CommentSerializer(comment).data, status=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
def filter_issues(issues, query):
|
||||
query_tokens = query.split(' ')
|
||||
for issue in issues:
|
||||
value = 0
|
||||
for token in query_tokens:
|
||||
if token in issue.description:
|
||||
value += 1
|
||||
if value > 0:
|
||||
yield {'search_score': value, 'issue': issue}
|
||||
|
||||
|
||||
@api_view(['GET'])
|
||||
@permission_classes([])
|
||||
# @permission_classes([IsAuthenticated])
|
||||
# @permission_required('view_item', raise_exception=True)
|
||||
def search_issues(request, event_slug, query):
|
||||
try:
|
||||
event = Event.objects.get(slug=event_slug)
|
||||
items = filter_issues(IssueThread.objects.filter(event=event), b64decode(query).decode('utf-8'))
|
||||
return Response(SearchResultSerializer(items, many=True).data)
|
||||
except Event.DoesNotExist:
|
||||
return Response(status=404)
|
||||
|
||||
|
||||
router = routers.SimpleRouter()
|
||||
router.register(r'tickets', IssueViewSet, basename='issues')
|
||||
#router.register(r'comments', CommentViewSet, basename='comments')
|
||||
# router.register(r'comments', CommentViewSet, basename='comments')
|
||||
router.register(r'shipping_vouchers', ShippingVoucherViewSet, basename='shipping_vouchers')
|
||||
|
||||
urlpatterns = ([
|
||||
re_path(r'tickets/states/$', get_available_states, name='get_available_states'),
|
||||
re_path(r'^tickets/(?P<pk>\d+)/reply/$', reply, name='reply'),
|
||||
re_path(r'^tickets/(?P<pk>\d+)/comment/$', add_comment, name='add_comment'),
|
||||
re_path(r'^tickets/manual/$', manual_ticket, name='manual_ticket'),
|
||||
re_path(r'^tickets/states/$', get_available_states, name='get_available_states'),
|
||||
re_path(r'^(?P<event_slug>[\w-]+)/tickets/manual/$', manual_ticket, name='manual_ticket'),
|
||||
re_path(r'^(?P<event_slug>[\w-]+)/tickets/(?P<query>.+)/$', search_issues, name='search_issues'),
|
||||
] + router.urls)
|
||||
|
|
|
@ -134,3 +134,14 @@ class IssueSerializer(serializers.ModelSerializer):
|
|||
|
||||
def get_queryset(self):
|
||||
return IssueThread.objects.all().order_by('-last_activity')
|
||||
|
||||
|
||||
class SearchResultSerializer(serializers.Serializer):
|
||||
search_score = serializers.IntegerField()
|
||||
item = IssueSerializer()
|
||||
|
||||
def to_representation(self, instance):
|
||||
return {**IssueSerializer(instance['item']).data, 'search_score': instance['search_score']}
|
||||
|
||||
class Meta:
|
||||
model = IssueThread
|
||||
|
|
|
@ -8,6 +8,8 @@ from tickets.models import IssueThread, StateChange, Comment
|
|||
from django.contrib.auth.models import Permission
|
||||
from knox.models import AuthToken
|
||||
|
||||
from base64 import b64encode
|
||||
|
||||
|
||||
class IssueApiTest(TestCase):
|
||||
|
||||
|
@ -230,7 +232,7 @@ class IssueApiTest(TestCase):
|
|||
self.assertEqual(file2.hash, response.json()[0]['timeline'][1]['attachments'][1]['hash'])
|
||||
|
||||
def test_manual_creation(self):
|
||||
response = self.client.post('/api/2/tickets/manual/',
|
||||
response = self.client.post('/api/2/evt/tickets/manual/',
|
||||
{'name': 'test issue', 'sender': 'test', 'recipient': 'test', 'body': 'test'},
|
||||
content_type='application/json')
|
||||
self.assertEqual(response.status_code, 201)
|
||||
|
@ -247,7 +249,7 @@ class IssueApiTest(TestCase):
|
|||
self.assertEqual(timeline[1]['subject'], 'test issue')
|
||||
self.assertEqual(timeline[1]['body'], 'test')
|
||||
|
||||
#def test_post_comment(self):
|
||||
# def test_post_comment(self):
|
||||
# issue = IssueThread.objects.create(
|
||||
# name="test issue",
|
||||
# )
|
||||
|
@ -315,3 +317,20 @@ class IssueApiTest(TestCase):
|
|||
self.assertEqual('pending_new', timeline[0]['state'])
|
||||
self.assertEqual('assignment', timeline[1]['type'])
|
||||
self.assertEqual(self.user.username, timeline[1]['assigned_to'])
|
||||
|
||||
|
||||
class IssueSearchTest(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.user = ExtendedUser.objects.create_user('testuser', 'test', 'test')
|
||||
self.user.user_permissions.add(*Permission.objects.all())
|
||||
self.user.save()
|
||||
self.token = AuthToken.objects.create(user=self.user)
|
||||
self.client = Client(headers={'Authorization': 'Token ' + self.token[1]})
|
||||
|
||||
def test_search(self):
|
||||
search_query = b64encode(b'abc').decode('utf-8')
|
||||
response = self.client.get(f'/api/2/evt/tickets/{search_query}/')
|
||||
self.assertEqual(200, response.status_code)
|
||||
self.assertEqual([], response.json())
|
||||
|
|
Loading…
Reference in a new issue