This commit is contained in:
j3d1 2024-07-18 21:11:53 +02:00
parent af00daca51
commit 1c9afb6bad
5 changed files with 54 additions and 24 deletions

View file

@ -1,4 +1,4 @@
from django.urls import path
from django.urls import re_path
from django.contrib.auth.decorators import permission_required
from rest_framework import routers, viewsets
from rest_framework.decorators import api_view, permission_classes
@ -35,8 +35,8 @@ def filter_items(items, query):
@api_view(['GET'])
@permission_classes([])
#@permission_classes([IsAuthenticated])
#@permission_required('view_item', raise_exception=True)
# @permission_classes([IsAuthenticated])
# @permission_required('view_item', raise_exception=True)
def search_items(request, event_slug, query):
try:
event = Event.objects.get(slug=event_slug)
@ -109,8 +109,12 @@ router.register(r'boxes', ContainerViewSet, basename='boxes')
router.register(r'box', ContainerViewSet, basename='boxes')
urlpatterns = router.urls + [
path('<event_slug>/items/', item),
path('<event_slug>/items/<query>/', search_items),
path('<event_slug>/item/', item),
path('<event_slug>/item/<id>/', item_by_id),
# path('<event_slug>/items/', item),
# path('<event_slug>/items/<query>/', search_items),
# path('<event_slug>/item/', item),
# path('<event_slug>/item/<id>/', item_by_id),
re_path(r'^(?P<event_slug>[\w-]+)/items/$', item, name='item'),
re_path(r'^(?P<event_slug>[\w-]+)/items/(?P<query>[-A-Za-z0-9+/]*={0,3})/$', search_items, name='search_items'),
re_path(r'^(?P<event_slug>[\w-]+)/item/$', item, name='item'),
re_path(r'^(?P<event_slug>[\w-]+)/item/(?P<id>\d+)/$', item_by_id, name='item_by_id'),
]

View file

@ -152,10 +152,13 @@ router.register(r'tickets', IssueViewSet, basename='issues')
# router.register(r'comments', CommentViewSet, basename='comments')
router.register(r'shipping_vouchers', ShippingVoucherViewSet, basename='shipping_vouchers')
# [-A-Za-z0-9+/]*={0,3}
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'^(?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'),
re_path(r'^(?P<event_slug>[\w-]+)/tickets/(?P<query>[-A-Za-z0-9+/]*={0,3})/$', search_issues,
name='search_issues'),
] + router.urls)

View file

@ -3,6 +3,7 @@ from datetime import datetime, timedelta
from django.test import TestCase, Client
from authentication.models import ExtendedUser
from inventory.models import Event
from mail.models import Email, EmailAttachment
from tickets.models import IssueThread, StateChange, Comment
from django.contrib.auth.models import Permission
@ -323,6 +324,7 @@ class IssueSearchTest(TestCase):
def setUp(self):
super().setUp()
self.event = Event.objects.create(slug='EVENT', name='Event')
self.user = ExtendedUser.objects.create_user('testuser', 'test', 'test')
self.user.user_permissions.add(*Permission.objects.all())
self.user.save()
@ -331,6 +333,6 @@ class IssueSearchTest(TestCase):
def test_search(self):
search_query = b64encode(b'abc').decode('utf-8')
response = self.client.get(f'/api/2/evt/tickets/{search_query}/')
response = self.client.get(f'/api/2/{self.event.slug}/tickets/{search_query}/')
self.assertEqual(200, response.status_code)
self.assertEqual([], response.json())

View file

@ -1,19 +1,17 @@
<template>
<form class="form-inline">
<input
class="form-control w-100"
type="search"
placeholder="Search"
aria-label="Search"
v-model="search_query"
@input="searchEventItems(search_query)"
@keyup.enter="dispatchSearch"
>
</form>
</template>
<script>
import {mapActions} from "vuex";
import {mapActions, mapGetters} from "vuex";
export default {
name: 'SearchBox',
@ -22,8 +20,24 @@ export default {
search_query: ''
}
},
computed: {
...mapGetters(['getActiveView'])
},
methods: {
...mapActions(['searchEventItems']),
...mapActions(['searchEventItems', 'searchEventTickets']),
isItemView() {
return this.getActiveView === 'items' || this.getActiveView === 'item';
},
isTicketView() {
return this.getActiveView === 'tickets' || this.getActiveView === 'ticket';
},
dispatchSearch() {
if (this.isItemView()) {
this.searchEventItems(this.search_query);
} else if (this.isTicketView()) {
this.searchEventTickets(this.search_query);
}
}
}
};
</script>

View file

@ -26,6 +26,7 @@ const store = createStore({
lastEvent: '37C3',
lastUsed: {},
searchQuery: '',
remember: false,
user: {
username: null,
@ -375,10 +376,9 @@ const store = createStore({
}
},
async searchEventItems({commit, getters, state}, query) {
const foo = utf8.encode(query);
const bar = base64.encode(foo);
const encoded_query = base64.encode(utf8.encode(query));
const {data, success} = await http.get(`/2/${getters.getEventSlug}/items/${bar}/`, state.user.token);
const {data, success} = await http.get(`/2/${getters.getEventSlug}/items/${encoded_query}/`, state.user.token);
if (data && success)
commit('replaceLoadedItems', data);
},
@ -427,6 +427,13 @@ const store = createStore({
if (data && success)
commit('replaceTickets', data);
},
async searchEventTickets({commit, getters, state}, query) {
const encoded_query = base64.encode(utf8.encode(query));
const {data, success} = await http.get(`/2/${getters.getEventSlug}/tickets/${encoded_query}/`, state.user.token);
if (data && success)
commit('replaceTickets', data);
},
async sendMail({commit, dispatch, state}, {id, message}) {
const {data, success} = await http.post(`/2/tickets/${id}/reply/`, {message}, state.user.token);
if (data && success) {