Skip to content

Commit

Permalink
Merge pull request #34 from ISSResearch/feat-issueresolve-1
Browse files Browse the repository at this point in the history
Feat issueresolve 1
  • Loading branch information
githubering182 authored Mar 15, 2024
2 parents b6912ba + cad5eab commit 67fbea4
Show file tree
Hide file tree
Showing 22 changed files with 573 additions and 108 deletions.
5 changes: 3 additions & 2 deletions backend-app/file/file_tests/models_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@ def test_create_file(self):
"project",
"author",
"status",
"is_downloaded"
"is_downloaded",
"validator",
)
.get(id=new_file.id)
),
set(credentials.values()).union({'v', False})
set(credentials.values()).union({'v', False, None})
)
self.assertEqual(init_count + 1, self.case.project.file_set.count())

Expand Down
20 changes: 18 additions & 2 deletions backend-app/file/file_tests/serializers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ def test_file_serializer(self):

self.assertEqual(
set(data.keys()),
data_keys.union({'upload_date', 'attributes', 'author_name'})
data_keys.union({
'upload_date',
"update_date",
'attributes',
'author_name',
"validator_name"
})
)
self.assertEqual(
{val for key, val in data.items() if key in data_keys},
Expand All @@ -42,14 +48,24 @@ def test_file_serializer(self):
self.assertEqual(data["attributes"][0].keys(), {"uid", "attributes"})

def test_update_file_serializer(self):
data = FileSerializer(self.case.file_, {'status': 'a'}, partial=True)
data = FileSerializer(
self.case.file_,
{'status': 'a'},
partial=True,
context={"validator": self.case.user}
)
init_date = data.instance.upload_date

self.assertIsNone(data.instance.validator)

if data.is_valid(): data.update_file()

updated_data = FileSerializer(self.case.file_).data

self.assertEqual(updated_data['status'], 'a')
self.assertFalse(bool(updated_data['attributes']))
self.assertIsNotNone(updated_data.get("validator_name"))
self.assertNotEqual(updated_data.get("update_date"), init_date)

def test_update_attribute_file_serializer(self):
self.case.attribute2 = self.case.attributegroup.attribute.create(
Expand Down
42 changes: 39 additions & 3 deletions backend-app/file/file_tests/services_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@
from project.models import Project
from user.models import CustomUser
from uuid import uuid4
from datetime import datetime as dt, timedelta as td
from django.utils import timezone as tz


class ViewServicesTest(TestCase, ViewSetServices):
date_format: str = "%Y-%m-%d"

@classmethod
def setUpClass(cls):
super().setUpClass()
Expand Down Expand Up @@ -146,9 +150,18 @@ def test_patch(self):
str(self.case.attributegroup.uid): [new_attr.id],
}
}
request = lambda payload={}: type(
"rq",
(object,),
{"data": payload, "user": self.case.user}
)

res, code = self._patch_file(self.case.file_.id, request_data)
invalid_res, invalid_code = self._patch_file(self.case.file_.id, {"status": 123})
valid_rq_init_date = File.objects.get(id=self.case.file_.id).update_date,

self.assertIsNone(File.objects.get(id=self.case.file_.id).validator)

res, code = self._patch_file(self.case.file_.id, request(request_data))
invalid_res, invalid_code = self._patch_file(self.case.file_.id, request({"status": 123}))

self.assertEqual(invalid_code, 400)
self.assertFalse(invalid_res["ok"])
Expand Down Expand Up @@ -179,6 +192,11 @@ def test_patch(self):
File.objects.get(id=self.case.file_.id).status,
"a"
)
self.assertNotEqual(
File.objects.get(id=self.case.file_.id).update_date,
valid_rq_init_date
)
self.assertIsNotNone(File.objects.get(id=self.case.file_.id).validator)

def test_form_query(self):
query = {}
Expand All @@ -199,6 +217,12 @@ def test_form_query(self):
query["author"] = self.admin
self._form_query_mixin(query)

query["from_"] = dt.now().strftime(self.date_format)
self._form_query_mixin(query)

query["to"] = (dt.now() + td(days=1)).strftime(self.date_format)
self._form_query_mixin(query)

def _form_query_mixin(self, data={}):
query, filter = self._get_query(**data)
res = self._form_query(
Expand All @@ -215,7 +239,9 @@ def _get_query(
status="",
downloaded=False,
author=[],
user=None
user=None,
from_="",
to=""
):
request_query = type(
"query",
Expand Down Expand Up @@ -248,6 +274,16 @@ def _get_query(
if author:
query.set("author[]", author)
filter["author__in"] = author
if from_:
query.set("from", from_)
filter["upload_date__gte"] = tz.make_aware(
dt.strptime(from_, self.date_format)
)
if to:
query.set("to", to)
filter["upload_date__lte"] = tz.make_aware(
dt.strptime(to, self.date_format)
)

return query, filter

Expand Down
9 changes: 8 additions & 1 deletion backend-app/file/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,18 @@ class File(Model):
file_name: CharField = CharField(max_length=255)
file_type: CharField = CharField(max_length=10)
status: CharField = CharField(max_length=1, choices=STATUSES, default='v')
upload_date: DateTimeField = DateTimeField(auto_now_add=True)
is_downloaded: BooleanField = BooleanField(default=False)
upload_date: DateTimeField = DateTimeField(auto_now_add=True)
update_date: DateTimeField = DateTimeField(auto_now_add=True, null=True)

project: ForeignKey = ForeignKey("project.Project", on_delete=DO_NOTHING)
author: ForeignKey = ForeignKey("user.CustomUser", on_delete=DO_NOTHING)
validator: ForeignKey = ForeignKey(
"user.CustomUser",
null=True,
on_delete=DO_NOTHING,
related_name="validator"
)

class Meta:
db_table = "file"
Expand Down
19 changes: 16 additions & 3 deletions backend-app/file/serializers.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,40 @@
from rest_framework.serializers import SerializerMethodField, ModelSerializer
from typing import Any
from django.utils import timezone
from collections import OrderedDict
from attribute.serializers import AttributeGroupSerializer
from .models import File
from user.models import CustomUser
from typing import Optional


class FileSerializer(ModelSerializer):
attributes: SerializerMethodField = SerializerMethodField()
author_name: SerializerMethodField = SerializerMethodField()
validator_name: SerializerMethodField = SerializerMethodField()

class Meta:
model = File
exclude = ("project", "author")
exclude = ("project", "author", "validator")

def get_attributes(self, instance: File) -> list[OrderedDict[str, Any]]:
return AttributeGroupSerializer(instance.attributegroup_set.all(), many=True).data

def get_author_name(self, instance: File) -> str: return instance.author.username

def get_validator_name(self, instance: File) -> str:
validator: Optional[CustomUser] = instance.validator
return validator and validator.username

def update_file(self) -> File:
super().save()
self.validated_data["update_date"] = timezone.now()
self.validated_data["validator"] = self.context.get("validator")

super().update(self.instance, self.validated_data)

self.instance.update_attributes(self.initial_data.get("attribute", {}))
self.instance.update_attributes(
self.initial_data.get("attribute", {}),
)

return self.instance

Expand Down
29 changes: 22 additions & 7 deletions backend-app/file/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
from rest_framework.views import Request
from django.db import connection
from django.db.models import Count, Subquery, QuerySet
from django.utils import timezone as tz
from attribute.models import Level, AttributeGroup as AGroup
from user.models import CustomUser
from json import loads
from typing import Any
from uuid import UUID
from datetime import datetime as dt
from .serializers import File, FileSerializer


Expand All @@ -28,21 +30,28 @@ class ViewSetServices:
("file_type__in", "type[]", True),
("status", "status", False),
("is_downloaded", "downloaded", False),
("author__in", "author[]", True)
("author__in", "author[]", True),
("upload_date__gte", "from", False),
("upload_date__lte", "to", False)
)

def _patch_file(
self,
file_id: str,
request_data: dict[str, Any]
request: Request
) -> tuple[dict[str, Any], int]:
# TODO: no handler for nofile case. imp tests after
file = File.objects \
.select_related("author") \
.prefetch_related("attributegroup_set") \
.get(id=file_id)

updated_file = FileSerializer(file, request_data, partial=True)
updated_file = FileSerializer(
file,
request.data,
partial=True,
context={"validator": request.user}
)
update_valid = updated_file.is_valid()

if update_valid: updated_file.update_file()
Expand Down Expand Up @@ -87,13 +96,19 @@ def _form_query(
else request_query.get(param)
)

if query_param: query[filter_name] = (
False if filter_name == "is_downloaded"
else query_param
)
if query_param:
query[filter_name] = self._get_param(filter_name, query_param)

return query

def _get_param(self, filter_name: str, query_param: Any) -> Any:
date_from_str = lambda d: tz.make_aware(dt.strptime(d, "%Y-%m-%d"))
match filter_name:
case "is_downloaded": return False
case "upload_date__gte": return date_from_str(query_param)
case "upload_date__lte": return date_from_str(query_param)
case _: return query_param

def _get_files(
self,
project_id: int,
Expand Down
2 changes: 1 addition & 1 deletion backend-app/file/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class FileViewSet(APIView, ViewSetServices):
permission_classes = (IsAuthenticated, FilePermission)

def patch(self, request: Request, fileID: str) -> Response:
response, status = self._patch_file(fileID, request.data)
response, status = self._patch_file(fileID, request)
return Response(response, status=status)

def delete(self, _, fileID: str) -> Response:
Expand Down
3 changes: 2 additions & 1 deletion frontend-app/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { UserContext } from "./context/User";
import { AlertContext } from "./context/Alert";
import { useState, useEffect } from "react";
import { ReactElement, useState, useEffect } from "react";
import { useUser, useAlerts } from "./hooks";
import { api } from "./config/api";
import AppRouter from "./components/AppRouter";
Expand All @@ -9,6 +9,7 @@ import StatusLoad from "./components/ui/StatusLoad";
import AlertManager from "./components/AlertManager";
import './app.css';

/** @returns {ReactElement} */
export default function App() {
const { user, initUser } = useUser();
const alertManager = useAlerts();
Expand Down
2 changes: 1 addition & 1 deletion frontend-app/src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
/* --issLightGreen: #99ff62; */
/* --issBrand: #004077; */
/* --issLightBrand: #01a4e0; */
--maxWidth: 1320px;
--maxWidth: 1920px;
}

* {
Expand Down
Loading

0 comments on commit 67fbea4

Please sign in to comment.