From 539945981a00bc93a9525e61e052563df701757a Mon Sep 17 00:00:00 2001 From: Andrew Liu <159852527+aliu39@users.noreply.github.com> Date: Fri, 12 Jul 2024 13:38:52 -0700 Subject: [PATCH 1/4] feat(prompts): support a visible status for un-hiding components --- src/sentry/api/endpoints/prompts_activity.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sentry/api/endpoints/prompts_activity.py b/src/sentry/api/endpoints/prompts_activity.py index c6de9c12175e96..f4fa2d7f7dd5db 100644 --- a/src/sentry/api/endpoints/prompts_activity.py +++ b/src/sentry/api/endpoints/prompts_activity.py @@ -16,7 +16,7 @@ from sentry.models.promptsactivity import PromptsActivity from sentry.utils.prompts import prompt_config -VALID_STATUSES = frozenset(("snoozed", "dismissed")) +VALID_STATUSES = frozenset(("snoozed", "dismissed", "visible")) # Endpoint to retrieve multiple PromptsActivity at once @@ -106,6 +106,9 @@ def put(self, request: Request, **kwargs): data["snoozed_ts"] = now elif status == "dismissed": data["dismissed_ts"] = now + elif status == "visible": + data["snoozed_ts"] = None + data["dismissed_ts"] = None try: with transaction.atomic(router.db_for_write(PromptsActivity)): From 4f2ec4efeeae9c089c4b730bc5c48ec16c7de178 Mon Sep 17 00:00:00 2001 From: Andrew Liu <159852527+aliu39@users.noreply.github.com> Date: Fri, 12 Jul 2024 13:51:13 -0700 Subject: [PATCH 2/4] Add unit test --- .../api/endpoints/test_prompts_activity.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/sentry/api/endpoints/test_prompts_activity.py b/tests/sentry/api/endpoints/test_prompts_activity.py index e10557f742b8cd..8def21c8ca2b3e 100644 --- a/tests/sentry/api/endpoints/test_prompts_activity.py +++ b/tests/sentry/api/endpoints/test_prompts_activity.py @@ -123,6 +123,32 @@ def test_snooze_legacy_path(self): self.path = reverse("sentry-api-0-prompts-activity") self.test_snooze() + def test_visible(self): + data = { + "organization_id": self.org.id, + "project_id": self.project.id, + "feature": "releases", + } + resp = self.client.get(self.path, data) + assert resp.status_code == 200 + assert resp.data.get("data", None) is None + + self.client.put( + self.path, + { + "organization_id": self.org.id, + "project_id": self.project.id, + "feature": "releases", + "status": "visible", + }, + ) + + resp = self.client.get(self.path, data) + assert resp.status_code == 200 + assert "data" in resp.data + assert resp.data["data"].get("dismissed_ts") is None + assert resp.data["data"].get("snoozed_ts") is None + def test_batched(self): data = { "organization_id": self.org.id, From af7fa9a1e8b340fa07e99c8ef18efe2511cfc0cb Mon Sep 17 00:00:00 2001 From: Andrew Liu <159852527+aliu39@users.noreply.github.com> Date: Fri, 12 Jul 2024 13:55:50 -0700 Subject: [PATCH 3/4] Add legacy and dismiss+visible tests --- .../api/endpoints/test_prompts_activity.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/sentry/api/endpoints/test_prompts_activity.py b/tests/sentry/api/endpoints/test_prompts_activity.py index 8def21c8ca2b3e..17b24dc6379b82 100644 --- a/tests/sentry/api/endpoints/test_prompts_activity.py +++ b/tests/sentry/api/endpoints/test_prompts_activity.py @@ -149,6 +149,46 @@ def test_visible(self): assert resp.data["data"].get("dismissed_ts") is None assert resp.data["data"].get("snoozed_ts") is None + def test_visible_legacy_path(self): + self.path = reverse("sentry-api-0-prompts-activity") + self.test_visible() + + def test_visible_after_dismiss(self): + data = { + "organization_id": self.org.id, + "project_id": self.project.id, + "feature": "releases", + } + resp = self.client.get(self.path, data) + assert resp.status_code == 200 + assert resp.data.get("data", None) is None + + self.client.put( + self.path, + { + "organization_id": self.org.id, + "project_id": self.project.id, + "feature": "releases", + "status": "dismiss", + }, + ) + + self.client.put( + self.path, + { + "organization_id": self.org.id, + "project_id": self.project.id, + "feature": "releases", + "status": "visible", + }, + ) + + resp = self.client.get(self.path, data) + assert resp.status_code == 200 + assert "data" in resp.data + assert resp.data["data"].get("dismissed_ts") is None + assert resp.data["data"].get("snoozed_ts") is None + def test_batched(self): data = { "organization_id": self.org.id, From 447c5c12dad50e360aa055027580346d3d9ed3b2 Mon Sep 17 00:00:00 2001 From: Andrew Liu <159852527+aliu39@users.noreply.github.com> Date: Sun, 14 Jul 2024 20:32:21 -0700 Subject: [PATCH 4/4] Type annotation to pass mypy --- src/sentry/api/endpoints/prompts_activity.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sentry/api/endpoints/prompts_activity.py b/src/sentry/api/endpoints/prompts_activity.py index f4fa2d7f7dd5db..cfc693d1cd0710 100644 --- a/src/sentry/api/endpoints/prompts_activity.py +++ b/src/sentry/api/endpoints/prompts_activity.py @@ -1,4 +1,5 @@ import calendar +from typing import Any from django.db import IntegrityError, router, transaction from django.db.models import Q @@ -100,7 +101,7 @@ def put(self, request: Request, **kwargs): else: fields["organization_id"] = 0 - data = {} + data: dict[str, Any] = {} now = calendar.timegm(timezone.now().utctimetuple()) if status == "snoozed": data["snoozed_ts"] = now