From 315a56be2cb440af397ff5795a9bd647343de508 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 8 Sep 2022 11:32:09 -0400 Subject: [PATCH 01/12] Add `days_left` field --- .../api/v1/endpoints/privacy_request_endpoints.py | 12 +++++++++++- src/fidesops/ops/schemas/privacy_request.py | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py b/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py index 1f31ce2f1..2f791cd22 100644 --- a/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py +++ b/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py @@ -4,7 +4,7 @@ import io import logging from collections import defaultdict -from datetime import datetime +from datetime import datetime, timezone from typing import Any, Callable, DefaultDict, Dict, List, Optional, Set, Union import sqlalchemy @@ -328,6 +328,14 @@ def privacy_request_csv_download( return response +def get_days_left(self: PrivacyRequest): + if self.due_date is None: + return None + + delta = self.due_date - datetime.now(timezone.utc) + return delta.days + + def execution_and_audit_logs_by_dataset_name( self: PrivacyRequest, ) -> DefaultDict[str, List["ExecutionLog"]]: @@ -598,6 +606,8 @@ def get_request_status( else: PrivacyRequest.execution_and_audit_logs_by_dataset = property(lambda self: None) + PrivacyRequest.days_left = property(get_days_left) + paginated = paginate(query, params) if include_identities: # Conditionally include the cached identity data in the response if diff --git a/src/fidesops/ops/schemas/privacy_request.py b/src/fidesops/ops/schemas/privacy_request.py index 65955e059..11a25bfa0 100644 --- a/src/fidesops/ops/schemas/privacy_request.py +++ b/src/fidesops/ops/schemas/privacy_request.py @@ -134,7 +134,6 @@ class RowCountRequest(BaseSchema): class CheckpointActionRequiredDetails(CheckpointActionRequired): - collection: Optional[str] = None # type: ignore @@ -166,6 +165,7 @@ class PrivacyRequestResponse(BaseSchema): policy: PolicySchema action_required_details: Optional[CheckpointActionRequiredDetails] = None resume_endpoint: Optional[str] + days_left: Optional[str] class Config: """Set orm_mode and use_enum_values""" From 9ad97ea70632971d2c512c6b4a4448b279f771d0 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 8 Sep 2022 13:23:23 -0400 Subject: [PATCH 02/12] Fix lints and update tests --- .../ops/api/v1/endpoints/privacy_request_endpoints.py | 2 +- src/fidesops/ops/schemas/privacy_request.py | 2 +- tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py b/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py index 2f791cd22..0257cfacf 100644 --- a/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py +++ b/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py @@ -328,7 +328,7 @@ def privacy_request_csv_download( return response -def get_days_left(self: PrivacyRequest): +def get_days_left(self: PrivacyRequest) -> Union[int, None]: if self.due_date is None: return None diff --git a/src/fidesops/ops/schemas/privacy_request.py b/src/fidesops/ops/schemas/privacy_request.py index 11a25bfa0..02fd2a6a5 100644 --- a/src/fidesops/ops/schemas/privacy_request.py +++ b/src/fidesops/ops/schemas/privacy_request.py @@ -165,7 +165,7 @@ class PrivacyRequestResponse(BaseSchema): policy: PolicySchema action_required_details: Optional[CheckpointActionRequiredDetails] = None resume_endpoint: Optional[str] - days_left: Optional[str] + days_left: Optional[int] class Config: """Set orm_mode and use_enum_values""" diff --git a/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py b/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py index bf71523b9..7603e76a3 100644 --- a/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py +++ b/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py @@ -571,6 +571,7 @@ def test_get_privacy_requests_by_id( { "id": privacy_request.id, "created_at": stringify_date(privacy_request.created_at), + "days_left": -1341, "started_processing_at": stringify_date( privacy_request.started_processing_at ), @@ -627,6 +628,7 @@ def test_get_privacy_requests_by_partial_id( { "id": privacy_request.id, "created_at": stringify_date(privacy_request.created_at), + "days_left": -1341, "started_processing_at": stringify_date( privacy_request.started_processing_at ), @@ -983,6 +985,7 @@ def test_verbose_privacy_requests( { "id": privacy_request.id, "created_at": stringify_date(privacy_request.created_at), + "days_left": -1341, "started_processing_at": stringify_date( privacy_request.started_processing_at ), @@ -2031,6 +2034,7 @@ def test_resume_privacy_request( assert response_body == { "id": privacy_request.id, "created_at": stringify_date(privacy_request.created_at), + "days_left": None, "started_processing_at": stringify_date( privacy_request.started_processing_at ), From c482701d4b677b1aacb6a601f8ddae98672e9b45 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 8 Sep 2022 14:21:58 -0400 Subject: [PATCH 03/12] Move property to model --- .../api/v1/endpoints/privacy_request_endpoints.py | 8 -------- src/fidesops/ops/models/privacy_request.py | 13 +++++++++++-- .../v1/endpoints/test_privacy_request_endpoints.py | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py b/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py index 0257cfacf..d51ecad9a 100644 --- a/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py +++ b/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py @@ -328,12 +328,6 @@ def privacy_request_csv_download( return response -def get_days_left(self: PrivacyRequest) -> Union[int, None]: - if self.due_date is None: - return None - - delta = self.due_date - datetime.now(timezone.utc) - return delta.days def execution_and_audit_logs_by_dataset_name( @@ -606,8 +600,6 @@ def get_request_status( else: PrivacyRequest.execution_and_audit_logs_by_dataset = property(lambda self: None) - PrivacyRequest.days_left = property(get_days_left) - paginated = paginate(query, params) if include_identities: # Conditionally include the cached identity data in the response if diff --git a/src/fidesops/ops/models/privacy_request.py b/src/fidesops/ops/models/privacy_request.py index fee090cba..3027bead3 100644 --- a/src/fidesops/ops/models/privacy_request.py +++ b/src/fidesops/ops/models/privacy_request.py @@ -4,9 +4,9 @@ import json import logging -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from enum import Enum as EnumType -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Optional, Union from celery.result import AsyncResult from fideslib.cryptography.cryptographic_util import hash_with_salt @@ -137,6 +137,14 @@ def generate_request_callback_jwe(webhook: PolicyPreWebhook) -> str: return generate_jwe(json.dumps(jwe.dict()), config.security.app_encryption_key) +def get_days_left(self: PrivacyRequest) -> Union[int, None]: + if self.due_date is None: + return None + + delta = self.due_date - datetime.now(timezone.utc) + return delta.days + + class PrivacyRequest(Base): # pylint: disable=R0904 """ The DB ORM model to describe current and historic PrivacyRequests. A privacy request is a @@ -211,6 +219,7 @@ class PrivacyRequest(Base): # pylint: disable=R0904 paused_at = Column(DateTime(timezone=True), nullable=True) identity_verified_at = Column(DateTime(timezone=True), nullable=True) due_date = Column(DateTime(timezone=True), nullable=True) + days_left = property(get_days_left) @classmethod def create(cls, db: Session, *, data: Dict[str, Any]) -> FidesBase: diff --git a/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py b/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py index 7603e76a3..5b4c45583 100644 --- a/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py +++ b/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py @@ -2034,7 +2034,7 @@ def test_resume_privacy_request( assert response_body == { "id": privacy_request.id, "created_at": stringify_date(privacy_request.created_at), - "days_left": None, + "days_left": -1341, "started_processing_at": stringify_date( privacy_request.started_processing_at ), From 7611abdcd6de2062b2c25dcd3de0cb03cccb3900 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 8 Sep 2022 14:24:20 -0400 Subject: [PATCH 04/12] Run black --- src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py b/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py index d51ecad9a..09f9695a8 100644 --- a/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py +++ b/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py @@ -328,8 +328,6 @@ def privacy_request_csv_download( return response - - def execution_and_audit_logs_by_dataset_name( self: PrivacyRequest, ) -> DefaultDict[str, List["ExecutionLog"]]: From 483d4c727a3f736f78ffcc5e08b03f0fe2df49be Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 8 Sep 2022 14:25:34 -0400 Subject: [PATCH 05/12] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2804a70f9..513b43f9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ The types of changes are: * Added `execution_timeframe` to Policy model and schema [#1244](https://github.com/ethyca/fidesops/pull/1244) * Added `due_date` to Privacy request model [#1259](https://github.com/ethyca/fidesops/pull/1259) * Wrap up the email connector - it sends an email with erasure instructions as part of request execution [#1246](https://github.com/ethyca/fidesops/pull/1246) +* Added `days_left` field to Privacy request response [#1281](https://github.com/ethyca/fidesops/pull/1281) ### Docs From 4a451bb43e7de64c56c75c0a2cbe672e6f767c84 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 8 Sep 2022 15:10:23 -0400 Subject: [PATCH 06/12] Add new test and fix issue --- src/fidesops/ops/models/privacy_request.py | 2 +- .../test_privacy_request_endpoints.py | 37 ++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/fidesops/ops/models/privacy_request.py b/src/fidesops/ops/models/privacy_request.py index 3027bead3..c86cf95e7 100644 --- a/src/fidesops/ops/models/privacy_request.py +++ b/src/fidesops/ops/models/privacy_request.py @@ -141,7 +141,7 @@ def get_days_left(self: PrivacyRequest) -> Union[int, None]: if self.due_date is None: return None - delta = self.due_date - datetime.now(timezone.utc) + delta = self.due_date.date() - datetime.now(timezone.utc).date() return delta.days diff --git a/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py b/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py index 5b4c45583..fc1b300be 100644 --- a/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py +++ b/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py @@ -2,7 +2,7 @@ import csv import io import json -from datetime import datetime +from datetime import datetime, timedelta from typing import List from unittest import mock @@ -1325,6 +1325,41 @@ def test_get_failed_request_resume_info_from_email_send( } assert data["resume_endpoint"] == f"/privacy-request/{privacy_request.id}/retry" + @pytest.mark.parametrize( + "due_date, days_left", + [ + ( + datetime.utcnow() + timedelta(days=7), + 7, + ), + ( + datetime.utcnow(), + 0, + ), + ( + datetime.utcnow() + timedelta(days=-7), + -7, + ), + ], + ) + def test_get_privacy_requests_sets_days_left( + self, + api_client: TestClient, + db, + url, + generate_auth_header, + privacy_request, + due_date, + days_left, + ): + privacy_request.due_date = due_date + privacy_request.save(db) + + auth_header = generate_auth_header(scopes=[PRIVACY_REQUEST_READ]) + response = api_client.get(url, headers=auth_header) + data = response.json()["items"][0] + assert data["days_left"] == days_left + class TestGetExecutionLogs: @pytest.fixture(scope="function") From eda584aa3cd2f719087cf21fa6c93dcda72b15f3 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 8 Sep 2022 15:21:48 -0400 Subject: [PATCH 07/12] Fix pylint issue --- src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py b/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py index 09f9695a8..1f31ce2f1 100644 --- a/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py +++ b/src/fidesops/ops/api/v1/endpoints/privacy_request_endpoints.py @@ -4,7 +4,7 @@ import io import logging from collections import defaultdict -from datetime import datetime, timezone +from datetime import datetime from typing import Any, Callable, DefaultDict, Dict, List, Optional, Set, Union import sqlalchemy From bb75135fc9a295d849e16c455012e526a299be9e Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 8 Sep 2022 15:42:20 -0400 Subject: [PATCH 08/12] Fix brittle tests issue --- .../test_privacy_request_endpoints.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py b/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py index fc1b300be..5b30ec9d0 100644 --- a/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py +++ b/tests/ops/api/v1/endpoints/test_privacy_request_endpoints.py @@ -559,7 +559,10 @@ def test_get_privacy_requests_by_id( privacy_request, postgres_execution_log, mongo_execution_log, + db, ): + privacy_request.due_date = None + privacy_request.save(db=db) auth_header = generate_auth_header(scopes=[PRIVACY_REQUEST_READ]) response = api_client.get( url + f"?request_id={privacy_request.id}", headers=auth_header @@ -571,7 +574,7 @@ def test_get_privacy_requests_by_id( { "id": privacy_request.id, "created_at": stringify_date(privacy_request.created_at), - "days_left": -1341, + "days_left": None, "started_processing_at": stringify_date( privacy_request.started_processing_at ), @@ -616,7 +619,10 @@ def test_get_privacy_requests_by_partial_id( privacy_request, postgres_execution_log, mongo_execution_log, + db, ): + privacy_request.due_date = None + privacy_request.save(db=db) auth_header = generate_auth_header(scopes=[PRIVACY_REQUEST_READ]) response = api_client.get( url + f"?request_id={privacy_request.id[:5]}", headers=auth_header @@ -628,7 +634,7 @@ def test_get_privacy_requests_by_partial_id( { "id": privacy_request.id, "created_at": stringify_date(privacy_request.created_at), - "days_left": -1341, + "days_left": None, "started_processing_at": stringify_date( privacy_request.started_processing_at ), @@ -972,6 +978,9 @@ def test_verbose_privacy_requests( db, ): """Test privacy requests endpoint with verbose query param to show execution logs""" + privacy_request.due_date = None + privacy_request.save(db) + auth_header = generate_auth_header(scopes=[PRIVACY_REQUEST_READ]) response = api_client.get(url + f"?verbose=True", headers=auth_header) assert 200 == response.status_code @@ -985,7 +994,7 @@ def test_verbose_privacy_requests( { "id": privacy_request.id, "created_at": stringify_date(privacy_request.created_at), - "days_left": -1341, + "days_left": None, "started_processing_at": stringify_date( privacy_request.started_processing_at ), @@ -2056,6 +2065,7 @@ def test_resume_privacy_request( db, ): privacy_request.status = PrivacyRequestStatus.paused + privacy_request.due_date = None privacy_request.save(db=db) auth_header = generate_webhook_auth_header( webhook=policy_pre_execution_webhooks[0] @@ -2069,7 +2079,7 @@ def test_resume_privacy_request( assert response_body == { "id": privacy_request.id, "created_at": stringify_date(privacy_request.created_at), - "days_left": -1341, + "days_left": None, "started_processing_at": stringify_date( privacy_request.started_processing_at ), From ffb6f60be60ffb836269f5f21962386cd8dad82d Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 8 Sep 2022 17:23:30 -0400 Subject: [PATCH 09/12] Add days left tag to table and details page --- .../src/features/common/DaysLeftTag.tsx | 37 +++++++++++++++++++ .../features/privacy-requests/RequestRow.tsx | 4 ++ .../privacy-requests/RequestTable.tsx | 1 + .../src/features/privacy-requests/types.ts | 1 + .../subject-request/RequestDetails.tsx | 5 ++- 5 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 clients/ops/admin-ui/src/features/common/DaysLeftTag.tsx diff --git a/clients/ops/admin-ui/src/features/common/DaysLeftTag.tsx b/clients/ops/admin-ui/src/features/common/DaysLeftTag.tsx new file mode 100644 index 000000000..14c773e2b --- /dev/null +++ b/clients/ops/admin-ui/src/features/common/DaysLeftTag.tsx @@ -0,0 +1,37 @@ +import { Tag } from "@fidesui/react"; +import React from "react"; + +type DaysLeftTagProps = { + days_left: number | undefined; + include_text: boolean; +}; + +const DaysLeftTag = ({ days_left, include_text }: DaysLeftTagProps) => { + if (!days_left) { + return null; + } + + let backgroundColor = ""; + + if (days_left >= 10) { + backgroundColor = "green.500"; + } + + if (days_left < 10 && days_left > 4) { + backgroundColor = "orange.500"; + } + + if (days_left < 5) { + backgroundColor = "red.400"; + } + + const text = include_text ? `${days_left} days left` : days_left; + + return ( + + {text} + + ); +}; + +export default DaysLeftTag; diff --git a/clients/ops/admin-ui/src/features/privacy-requests/RequestRow.tsx b/clients/ops/admin-ui/src/features/privacy-requests/RequestRow.tsx index b7bccee50..96a54d0b1 100644 --- a/clients/ops/admin-ui/src/features/privacy-requests/RequestRow.tsx +++ b/clients/ops/admin-ui/src/features/privacy-requests/RequestRow.tsx @@ -15,6 +15,7 @@ import { useClipboard, useToast, } from "@fidesui/react"; +import DaysLeftTag from "common/DaysLeftTag"; import { formatDate } from "common/utils"; import { useRouter } from "next/router"; import React, { useRef, useState } from "react"; @@ -151,6 +152,9 @@ const RequestRow: React.FC<{ request: PrivacyRequest }> = ({ request }) => { + + + = () => { Status + Days Left Request Type Subject Identity Time Received diff --git a/clients/ops/admin-ui/src/features/privacy-requests/types.ts b/clients/ops/admin-ui/src/features/privacy-requests/types.ts index 05f0dc2d2..a54250d0e 100644 --- a/clients/ops/admin-ui/src/features/privacy-requests/types.ts +++ b/clients/ops/admin-ui/src/features/privacy-requests/types.ts @@ -72,6 +72,7 @@ export interface PrivacyRequest { created_at: string; reviewed_by: string; id: string; + days_left?: number; } export interface PrivacyRequestResponse { diff --git a/clients/ops/admin-ui/src/features/subject-request/RequestDetails.tsx b/clients/ops/admin-ui/src/features/subject-request/RequestDetails.tsx index 1bc7dfbb0..1591b49d5 100644 --- a/clients/ops/admin-ui/src/features/subject-request/RequestDetails.tsx +++ b/clients/ops/admin-ui/src/features/subject-request/RequestDetails.tsx @@ -7,14 +7,15 @@ import { Text, useToast, } from "@fidesui/react"; +import DaysLeftTag from "common/DaysLeftTag"; import { isErrorWithDetail, isErrorWithDetailArray } from "common/helpers"; import { useRetryMutation } from "privacy-requests/privacy-requests.slice"; +import { PrivacyRequest } from "privacy-requests/types"; import { useState } from "react"; import ClipboardButton from "../common/ClipboardButton"; import RequestStatusBadge from "../common/RequestStatusBadge"; import RequestType from "../common/RequestType"; -import { PrivacyRequest } from "../privacy-requests/types"; type RequestDetailsProps = { subjectRequest: PrivacyRequest; @@ -94,6 +95,8 @@ const RequestDetails = ({ subjectRequest }: RequestDetailsProps) => { Retry )} + + From cd95e312005123a4a3b68f4b9fd91706c0931da3 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 8 Sep 2022 17:25:51 -0400 Subject: [PATCH 10/12] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68303ffe9..323e358bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ The types of changes are: * Added `days_left` field to Privacy request response [#1281](https://github.com/ethyca/fidesops/pull/1281) * Mapping Vault environment variables in docker-compose.yml [#1275](https://github.com/ethyca/fidesops/pull/1275) * Foundations for a new "manual_webhook" connector type [#1267](https://github.com/ethyca/fidesops/pull/1267) +* Add Days left display to admin ui [#1283](https://github.com/ethyca/fidesops/pull/1283) ### Docs From c410352be92726841d9bea40524029ac3ec27826 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Fri, 9 Sep 2022 10:27:11 -0400 Subject: [PATCH 11/12] Remove old code left from auto-merge --- src/fidesops/ops/models/privacy_request.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/fidesops/ops/models/privacy_request.py b/src/fidesops/ops/models/privacy_request.py index 4f20e67e4..39bcedcaa 100644 --- a/src/fidesops/ops/models/privacy_request.py +++ b/src/fidesops/ops/models/privacy_request.py @@ -4,7 +4,7 @@ import json import logging -from datetime import datetime, timedelta, timezone +from datetime import datetime, timedelta from enum import Enum as EnumType from typing import Any, Dict, List, Optional, Union @@ -138,14 +138,6 @@ def generate_request_callback_jwe(webhook: PolicyPreWebhook) -> str: return generate_jwe(json.dumps(jwe.dict()), config.security.app_encryption_key) -def get_days_left(self: PrivacyRequest) -> Union[int, None]: - if self.due_date is None: - return None - - delta = self.due_date.date() - datetime.now(timezone.utc).date() - return delta.days - - class PrivacyRequest(Base): # pylint: disable=R0904 """ The DB ORM model to describe current and historic PrivacyRequests. A privacy request is a @@ -220,7 +212,6 @@ class PrivacyRequest(Base): # pylint: disable=R0904 paused_at = Column(DateTime(timezone=True), nullable=True) identity_verified_at = Column(DateTime(timezone=True), nullable=True) due_date = Column(DateTime(timezone=True), nullable=True) - days_left = property(get_days_left) @property def days_left(self: PrivacyRequest) -> Union[int, None]: From 43019c0f47f7eb68285abbd089708ec47a18f618 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Mon, 12 Sep 2022 15:53:26 -0400 Subject: [PATCH 12/12] Address PR feedback --- .../src/features/common/DaysLeftTag.tsx | 31 +++++++++++-------- .../features/privacy-requests/RequestRow.tsx | 2 +- .../subject-request/RequestDetails.tsx | 2 +- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/clients/ops/admin-ui/src/features/common/DaysLeftTag.tsx b/clients/ops/admin-ui/src/features/common/DaysLeftTag.tsx index 14c773e2b..fd739c74d 100644 --- a/clients/ops/admin-ui/src/features/common/DaysLeftTag.tsx +++ b/clients/ops/admin-ui/src/features/common/DaysLeftTag.tsx @@ -2,30 +2,35 @@ import { Tag } from "@fidesui/react"; import React from "react"; type DaysLeftTagProps = { - days_left: number | undefined; - include_text: boolean; + daysLeft?: number; + includeText: boolean; }; -const DaysLeftTag = ({ days_left, include_text }: DaysLeftTagProps) => { - if (!days_left) { +const DaysLeftTag = ({ daysLeft, includeText }: DaysLeftTagProps) => { + if (!daysLeft) { return null; } let backgroundColor = ""; - if (days_left >= 10) { - backgroundColor = "green.500"; - } + switch (true) { + case daysLeft >= 10: + backgroundColor = "green.500"; + break; - if (days_left < 10 && days_left > 4) { - backgroundColor = "orange.500"; - } + case daysLeft < 10 && daysLeft > 4: + backgroundColor = "orange.500"; + break; + + case daysLeft < 5: + backgroundColor = "red.400"; + break; - if (days_left < 5) { - backgroundColor = "red.400"; + default: + break; } - const text = include_text ? `${days_left} days left` : days_left; + const text = includeText ? `${daysLeft} days left` : daysLeft; return ( diff --git a/clients/ops/admin-ui/src/features/privacy-requests/RequestRow.tsx b/clients/ops/admin-ui/src/features/privacy-requests/RequestRow.tsx index 96a54d0b1..aa213d86a 100644 --- a/clients/ops/admin-ui/src/features/privacy-requests/RequestRow.tsx +++ b/clients/ops/admin-ui/src/features/privacy-requests/RequestRow.tsx @@ -153,7 +153,7 @@ const RequestRow: React.FC<{ request: PrivacyRequest }> = ({ request }) => { - + { )} - +