Skip to content

Commit

Permalink
feat: top level observation review list (#2337)
Browse files Browse the repository at this point in the history
  • Loading branch information
StefanFl authored Dec 11, 2024
1 parent 1930d46 commit a61a360
Show file tree
Hide file tree
Showing 15 changed files with 559 additions and 309 deletions.
50 changes: 46 additions & 4 deletions backend/application/core/api/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,16 +284,58 @@ class ObservationLogFilter(FilterSet):
origin_component_name_version = CharFilter(
field_name="observation__origin_component_name_version", lookup_expr="icontains"
)
origin_docker_image_name_tag_short = CharFilter(
field_name="observation__origin_docker_image_name_tag_short",
lookup_expr="icontains",
)
origin_endpoint_hostname = CharFilter(
field_name="observation__origin_endpoint_hostname", lookup_expr="icontains"
)
origin_source_file = CharFilter(
field_name="observation__origin_source_file", lookup_expr="icontains"
)
origin_cloud_qualified_resource = CharFilter(
field_name="observation__origin_cloud_qualified_resource",
lookup_expr="icontains",
)
origin_kubernetes_qualified_resource = CharFilter(
field_name="observation__origin_kubernetes_qualified_resource",
lookup_expr="icontains",
)

ordering = OrderingFilter(
# tuple-mapping retains order
fields=(
("id", "id"),
("user__full_name", "user_full_name"),
("observation__product__name", "product_name"),
("observation__product__product_group__name", "product.product_group_name"),
("observation__branch__name", "branch_name"),
("observation__title", "observation_title"),
("observation__product__name", "observation_data.product_data.name"),
(
"observation__product__product_group__name",
"observation_data.product_data.product_group_name",
),
("observation__branch__name", "observation_data.branch_name"),
("observation__title", "observation_data.title"),
(
"observation__origin_component_name_version",
"observation_data.origin_component_name_version",
),
(
"observation__origin_docker_image_name_tag_short",
"observation_data.origin_docker_image_name_tag_short",
),
(
"observation__origin_endpoint_hostname",
"observation_data.origin_endpoint_hostname",
),
("observation__origin_source_file", "observation_data.origin_source_file"),
(
"observation__origin_cloud_qualified_resource",
"observation_data.origin_cloud_qualified_resource",
),
(
"observation__origin_kubernetes_qualified_resource",
"observation_data.origin_kubernetes_qualified_resource",
),
("severity", "severity"),
("status", "status"),
("comment", "comment"),
Expand Down
4 changes: 4 additions & 0 deletions backend/application/core/api/serializers_observation.py
Original file line number Diff line number Diff line change
Expand Up @@ -593,3 +593,7 @@ class PotentialDuplicateSerializer(ModelSerializer):
class Meta:
model = Potential_Duplicate
fields = "__all__"


class CountSerializer(Serializer):
count = IntegerField()
35 changes: 32 additions & 3 deletions backend/application/core/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.status import HTTP_204_NO_CONTENT
from rest_framework.status import HTTP_200_OK, HTTP_204_NO_CONTENT
from rest_framework.viewsets import GenericViewSet, ModelViewSet

from application.access_control.services.authorization import user_has_permission_or_403
Expand Down Expand Up @@ -40,6 +40,7 @@
UserHasServicePermission,
)
from application.core.api.serializers_observation import (
CountSerializer,
EvidenceSerializer,
ObservationAssessmentSerializer,
ObservationBulkAssessmentSerializer,
Expand Down Expand Up @@ -626,6 +627,18 @@ def bulk_assessment(self, request):
)
return Response(status=HTTP_204_NO_CONTENT)

@extend_schema(
methods=["GET"],
request=None,
responses={HTTP_200_OK: CountSerializer},
)
@action(detail=False, methods=["get"])
def count_reviews(self, request):
count = (
get_observations().filter(current_status=Status.STATUS_IN_REVIEW).count()
)
return Response(status=HTTP_200_OK, data={"count": count})


class ObservationTitleViewSet(GenericViewSet, ListModelMixin, RetrieveModelMixin):
serializer_class = ObservationTitleSerializer
Expand Down Expand Up @@ -684,11 +697,11 @@ def approval(self, request, pk=None):
return Response()

@extend_schema(
methods=["PATCH"],
methods=["POST"],
request=ObservationLogBulkApprovalSerializer,
responses={HTTP_204_NO_CONTENT: None},
)
@action(detail=False, methods=["patch"])
@action(detail=False, methods=["post"])
def bulk_approval(self, request):
request_serializer = ObservationLogBulkApprovalSerializer(data=request.data)
if not request_serializer.is_valid():
Expand All @@ -701,6 +714,22 @@ def bulk_approval(self, request):
)
return Response(status=HTTP_204_NO_CONTENT)

@extend_schema(
methods=["GET"],
request=None,
responses={HTTP_200_OK: CountSerializer},
)
@action(detail=False, methods=["get"])
def count_approvals(self, request):
count = (
get_observation_logs()
.filter(
assessment_status=Assessment_Status.ASSESSMENT_STATUS_NEEDS_APPROVAL
)
.count()
)
return Response(status=HTTP_200_OK, data={"count": count})


class EvidenceViewSet(GenericViewSet, ListModelMixin, RetrieveModelMixin):
serializer_class = EvidenceSerializer
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import observation_logs from "./core/observation_logs";
import observations from "./core/observations";
import product_groups from "./core/product_groups";
import products from "./core/products";
import Reviews from "./core/reviews/Reviews";
import { Dashboard } from "./dashboard";
import parsers from "./import_observations/parsers";
import LicenseAdministration from "./licenses/license_administration/LicenseAdministration";
Expand Down Expand Up @@ -65,6 +66,9 @@ const App = () => {
<Route path="/license/licenses" element={<LicenseAdministration />} />
<Route path="/license/license_groups" element={<LicenseAdministration />} />
<Route path="/license/license_policies" element={<LicenseAdministration />} />
<Route path="/reviews" element={<Reviews />} />
<Route path="/reviews/observation_reviews" element={<Reviews />} />
<Route path="/reviews/observation_log_approvals" element={<Reviews />} />
<Route path="/user_settings" element={<UserSettings />} />
</CustomRoutes>
<Resource
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/commons/layout/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const Menu = ({ dense = false }: MenuProps) => {
dense={dense}
/>
<MenuItemLink
to="/observation_logs/needs_approval"
to="/reviews"
state={{ _scrollToTop: true }}
primaryText="Reviews"
leftIcon={<ChecklistIcon />}
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/core/observation_logs/AssessmentBulkApproval.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ const AssessmentBulkApproval = () => {

const assessmentUpdate = async (data: any) => {
setLoading(true);
const patch = {
const post_data = {
assessment_status: data.assessment_status,
approval_remark: data.approval_remark,
observation_logs: selectedIds,
};

httpClient(window.__RUNTIME_CONFIG__.API_BASE_URL + "/observation_logs/bulk_approval/", {
method: "PATCH",
body: JSON.stringify(patch),
method: "POST",
body: JSON.stringify(post_data),
})
.then(() => {
refresh();
Expand Down

This file was deleted.

Loading

0 comments on commit a61a360

Please sign in to comment.