diff --git a/logs_collector/collector/api/filters.py b/logs_collector/collector/api/filters.py index bfa635b..9143706 100644 --- a/logs_collector/collector/api/filters.py +++ b/logs_collector/collector/api/filters.py @@ -1,7 +1,9 @@ +from django import forms from django_filters.rest_framework import ( CharFilter, FilterSet, NumberFilter, + BaseInFilter, ) from django_filters import widgets @@ -9,21 +11,46 @@ from collector.models import Archive, Ticket from .utils import DateTimeFilterMixin +class TextareaCSVWidget(widgets.BaseCSVWidget, forms.Textarea): + """ + The widget should create textarea. + """ + def render(self, name, value, attrs=None, renderer=None): + print("Row value: ", value) + if not self._isiterable(value): + value = [value] + + if len(value) <= 1: + # delegate to main widget (Select, etc...) if not multiple values + value = value[0] if value else '' + return super(TextareaCSVWidget, self).render(name, value, attrs) + + value = ','.join(value) + return super(TextareaCSVWidget, self).render(name, value, attrs) + + +class NumberInFilter(BaseInFilter, NumberFilter): + """ + The filter should accept coma separated integers. + """ + pass + + class ArchiveFilter(DateTimeFilterMixin, FilterSet): class Meta: model = Archive fields = { - 'id': ['exact', 'in', 'lte', 'gte'], - 'ticket': ['exact', 'in', 'lte', 'gte'], + 'id': ['exact', 'lte', 'gte'], + 'ticket': ['exact', 'lte', 'gte'], 'time_create': ['exact', 'lte', 'gte'] } class TicketFilter(DateTimeFilterMixin, FilterSet): - number = NumberFilter( + number = NumberInFilter( field_name='number', - widget=widgets.CSVWidget(), + widget=TextareaCSVWidget(), ) user = CharFilter( field_name='user__username' diff --git a/logs_collector/collector/api/serializers.py b/logs_collector/collector/api/serializers.py index b1dc0bc..ad06a23 100644 --- a/logs_collector/collector/api/serializers.py +++ b/logs_collector/collector/api/serializers.py @@ -6,13 +6,13 @@ from drf_spectacular.openapi import OpenApiTypes from collector.models import Archive, Platform, Ticket -@extend_schema_field(OpenApiTypes.NUMBER) +@extend_schema_field(OpenApiTypes.INT) class TimestampField(serializers.Field): def to_representation(self, value) -> int: return value.timestamp() -@extend_schema_field(OpenApiTypes.NUMBER) +@extend_schema_field(OpenApiTypes.INT) class JsTimestampField(serializers.Field): def to_representation(self, value) -> int: return round(value.timestamp()*1000) @@ -26,7 +26,7 @@ class PublicArchiveUploadSerializer(serializers.ModelSerializer): class ArchiveSerializer(serializers.ModelSerializer): - time_create = JsTimestampField(read_only=True) + time_create = serializers.DateTimeField(read_only=True) class Meta: model = Archive @@ -41,8 +41,8 @@ class PlatformSerializer(serializers.ModelSerializer): class TicketSerializer(serializers.ModelSerializer): - time_create = JsTimestampField(read_only=True) - time_update = JsTimestampField(read_only=True) + time_create = serializers.DateTimeField(read_only=True) + time_update = serializers.DateTimeField(read_only=True) token = serializers.UUIDField(read_only=True) user = serializers.ReadOnlyField(source='user.username') @@ -59,3 +59,10 @@ class TicketSerializer(serializers.ModelSerializer): 'time_update', 'user' ] + + +class StorageInfoSerializer(serializers.Serializer): + total = serializers.IntegerField(read_only=True) + used = serializers.IntegerField(read_only=True) + free = serializers.IntegerField(read_only=True) + used_percent = serializers.IntegerField(read_only=True) diff --git a/logs_collector/collector/api/tests/test_urls.py b/logs_collector/collector/api/tests/test_urls.py index 9f98ece..32030ab 100644 --- a/logs_collector/collector/api/tests/test_urls.py +++ b/logs_collector/collector/api/tests/test_urls.py @@ -29,3 +29,7 @@ class TestUrls(TestCase): def test_detail_platform_url_is_resolved(self): url = reverse('collector_api:platform-detail', args=['vm6']) self.assertEquals(resolve(url).func.cls, views.PlatformViewSet) + + def test_storage_info_url_is_resolved(self): + url = reverse('collector_api:storage-info') + self.assertEquals(resolve(url).func.cls, views.StorageInfo) diff --git a/logs_collector/collector/api/views.py b/logs_collector/collector/api/views.py index 00b5ca7..5e550a5 100644 --- a/logs_collector/collector/api/views.py +++ b/logs_collector/collector/api/views.py @@ -28,7 +28,8 @@ from .serializers import ( PublicArchiveUploadSerializer, ArchiveSerializer, PlatformSerializer, - TicketSerializer + TicketSerializer, + StorageInfoSerializer, ) @@ -129,6 +130,6 @@ class TicketViewSet(viewsets.ModelViewSet): class StorageInfo(views.APIView): """Info about storage total/used/free space""" - + @extend_schema(responses=StorageInfoSerializer) def get(self, request): return Response(get_mount_fs_info(settings.MEDIA_ROOT)) diff --git a/logs_collector/collector/context_processors.py b/logs_collector/collector/context_processors.py index 263a36e..bf49479 100644 --- a/logs_collector/collector/context_processors.py +++ b/logs_collector/collector/context_processors.py @@ -13,4 +13,4 @@ def metadata(request): def storage_info(request): - return get_mount_fs_info(settings.MEDIA_ROOT) + return {'storage': get_mount_fs_info(settings.MEDIA_ROOT)} diff --git a/logs_collector/collector/static/collector/js/helpers.js b/logs_collector/collector/static/collector/js/helpers.js index f48ed67..df1b231 100644 --- a/logs_collector/collector/static/collector/js/helpers.js +++ b/logs_collector/collector/static/collector/js/helpers.js @@ -38,7 +38,7 @@ const updateStorageInfo = () => { dataType: "json", success: function (data, textStatus, jqXHR) { // JSON answer: - let storage = data.storage + let storage = data; // set updated fields: let storageInfoNewFields = [ `Total: ${sizify(storage.total)}`, diff --git a/logs_collector/collector/utils/helpers.py b/logs_collector/collector/utils/helpers.py index bff3ce6..526a1f0 100644 --- a/logs_collector/collector/utils/helpers.py +++ b/logs_collector/collector/utils/helpers.py @@ -35,4 +35,4 @@ def get_mount_fs_info(path): mount_info['used_percent'] = round( mount_info['used'] / mount_info['total'] * 100 ) - return {'storage': mount_info} + return mount_info