Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improvement(highlights): send notification to action item assignee #558

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions argus/backend/controller/views_widgets/highlights.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from dataclasses import dataclass, asdict
from datetime import datetime, UTC
from dataclasses import asdict
from uuid import UUID

from flask import Blueprint, request, g
Expand Down Expand Up @@ -80,6 +79,9 @@ def set_assignee():
payload = HighlightSetAssignee(**get_payload(request))
service = HighlightsService()
updated_action_item = service.set_assignee(payload)
if payload.assignee_id:
service.send_action_notification(sender_id=g.user.id, username=g.user.username, view_id=payload.view_id,
assignee_id=payload.assignee_id, action=updated_action_item.content)
return {"status": "ok", "response": asdict(updated_action_item)}


Expand Down
2 changes: 2 additions & 0 deletions argus/backend/models/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,12 +236,14 @@ class ArgusNotificationTypes(str, Enum):
StatusChange = "TYPE_STATUS_CHANGE"
AssigneeChange = "TYPE_ASSIGNEE_CHANGE"
ScheduleChange = "TYPE_SCHEDULE_CHANGE"
ViewActionItemAssignee = "TYPE_VIEW_ACTION_ITEM_ASSIGNEE"


class ArgusNotificationSourceTypes(str, Enum):
TestRun = "TEST_RUN"
Schedule = "SCHEDULE"
Comment = "COMMENT"
ViewActionItem = "VIEW_ACTION_ITEM"


class ArgusNotificationState(IntEnum):
Expand Down
4 changes: 4 additions & 0 deletions argus/backend/service/notification_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class NotificationSenderBase:
ArgusNotificationTypes.StatusChange: "A run you are assigned to changed status",
ArgusNotificationTypes.AssigneeChange: "You were assigned to a run",
ArgusNotificationTypes.ScheduleChange: "You were assigned to a schedule",
ArgusNotificationTypes.ViewActionItemAssignee: "You were assigned to a view action item",
}

CONTENT_TEMPLATES = {}
Expand Down Expand Up @@ -95,6 +96,8 @@ class ArgusDBNotificationSaver(NotificationSenderBase):
CONTENT_TEMPLATES = {
ArgusNotificationTypes.Mention: lambda p: render_template("notifications/mention.html.j2", **p if p else {}),
ArgusNotificationTypes.AssigneeChange: lambda p: render_template("notifications/assigned.html.j2", **p if p else {}),
ArgusNotificationTypes.ViewActionItemAssignee: lambda p: render_template(
"notifications/view_action_item_assigned.html.j2", **p if p else {}),
}

def send_notification(self, receiver: UUID, sender: UUID, notification_type: ArgusNotificationTypes, source_type: ArgusNotificationSourceTypes,
Expand All @@ -120,6 +123,7 @@ class EmailNotificationServiceSender(NotificationSenderBase):
ArgusNotificationTypes.Mention: lambda p: render_template(
"notifications/email_mention.html.j2", **p if p else {}),
ArgusNotificationTypes.AssigneeChange: lambda p: render_template("notifications/assigned_email.html.j2", **p if p else {}),
ArgusNotificationTypes.ViewActionItemAssignee: lambda p: render_template("notifications/view_action_item_assigned_email.html.j2", **p if p else {}),
}

def __init__(self):
Expand Down
30 changes: 27 additions & 3 deletions argus/backend/service/views_widgets/highlights.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

from argus.backend.db import ScyllaCluster
from argus.backend.models.view_widgets import WidgetHighlights, WidgetComment
from argus.backend.models.web import ArgusNotificationTypes, ArgusNotificationSourceTypes, ArgusUserView
from argus.backend.service.notification_manager import NotificationManagerService


@dataclass
Expand Down Expand Up @@ -71,13 +73,15 @@ class CommentUpdate:
created_at: float
content: str


@dataclass
class CommentDelete:
view_id: UUID
index: int
highlight_created_at: float
created_at: float


@dataclass
class Comment:
view_id: UUID
Expand Down Expand Up @@ -129,8 +133,11 @@ class HighlightSetAssignee:
view_id: UUID
index: int
created_at: float
assignee_id: str | None = None
assignee_id: UUID | None = None

def __post_init__(self):
if self.assignee_id and not isinstance(self.assignee_id, UUID):
self.assignee_id = UUID(self.assignee_id)

@dataclass
class HighlightSetCompleted:
Expand Down Expand Up @@ -174,7 +181,7 @@ def archive_highlight(self, payload: HighlightArchive):
entry.archived_at = datetime.now(UTC)
entry.save()

def unarchive_highlight(self, payload: HighlightArchive):
def unarchive_highlight(self, payload: HighlightArchive):
entry = WidgetHighlights.objects(
view_id=payload.view_id,
index=payload.index,
Expand Down Expand Up @@ -212,7 +219,7 @@ def set_assignee(self, payload: HighlightSetAssignee) -> ActionItem:
if payload.assignee_id is None:
entry.assignee_id = None
else:
entry.assignee_id = UUID(payload.assignee_id)
entry.assignee_id = payload.assignee_id
entry.save()
return ActionItem.from_db_model(entry)

Expand Down Expand Up @@ -295,3 +302,20 @@ def get_comments(self, view_id: UUID, index: int, highlight_created_at: float) -
highlight_created_at = datetime.fromtimestamp(highlight_created_at, tz=UTC)
comments = WidgetComment.objects(view_id=view_id, index=index, highlight_at=highlight_created_at)
return [Comment.from_db_model(c) for c in comments]

def send_action_notification(self, sender_id: UUID, username: str, view_id: UUID, assignee_id: UUID, action: str):
view = ArgusUserView.get(id=view_id)
NotificationManagerService().send_notification(
receiver=assignee_id,
sender=sender_id,
notification_type=ArgusNotificationTypes.ViewActionItemAssignee,
source_type=ArgusNotificationSourceTypes.ViewActionItem,
source_id=view_id,
source_message="",
content_params={
"username": username,
"view_name": view.name,
"display_name": view.display_name,
"action": action,
}
)
6 changes: 4 additions & 2 deletions argus/backend/tests/view_widgets/test_highlights_api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
from datetime import datetime, UTC
from unittest.mock import patch
from uuid import uuid4, UUID

from flask import g
Expand Down Expand Up @@ -303,8 +304,8 @@ def test_set_completed_should_not_work_for_highlight(flask_client):
assert response.json["status"] == "error"
assert response.json["response"]["exception"] == "NotFound"


def test_set_assignee_should_set_assignee_for_action_item(flask_client):
@patch("argus.backend.controller.views_widgets.highlights.HighlightsService.send_action_notification")
def test_set_assignee_should_set_assignee_for_action_item(notification, flask_client):
view_id = str(uuid4())
created_at = datetime.now(UTC)
action_item_entry = WidgetHighlights(
Expand Down Expand Up @@ -333,6 +334,7 @@ def test_set_assignee_should_set_assignee_for_action_item(flask_client):
assert response.status_code == 200
assert response.json["status"] == "ok"
assert response.json["response"]["assignee_id"] == new_assignee_id
assert notification.call_count == 1

updated_entry = WidgetHighlights.objects(view_id=UUID(view_id), index=0, created_at=created_at).first()
assert str(updated_entry.assignee_id) == new_assignee_id
Expand Down
3 changes: 2 additions & 1 deletion frontend/Common/ArgusNotification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export enum NotificationTypes {

export enum NotificationSource {
Comment = "COMMENT",
TestRun = "TEST_RUN"
TestRun = "TEST_RUN",
ViewActionItem = "VIEW_ACTION_ITEM",
}

export interface ArgusNotificationJSON {
Expand Down
4 changes: 4 additions & 0 deletions frontend/Profile/Notification.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
const ComponentSourceMap: ComponentSourceType = {
[NotificationSource.Comment]: NotificationCommentWrapper,
[NotificationSource.TestRun]: NotificationTestRunWrapper,
[NotificationSource.ViewActionItem]: NotificationTestRunWrapper,
};

const SupportDataFetch = {
Expand All @@ -33,6 +34,9 @@
[NotificationSource.TestRun]: async () => {
return {};
},
[NotificationSource.ViewActionItem]: async () => {
return {};
},
};

const setNotificationAsRead = async function() {
Expand Down
3 changes: 3 additions & 0 deletions templates/notifications/view_action_item_assigned.html.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
You were assigned by <span class='fw-bold'>@{{ username }}</span> to View Action <a
href='{{ url_for("main.view_dashboard", **{ "view_name": view_name}) }}'>{{ display_name }}</a>.
<p>Action: {{ action }}</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div>You were assigned by <span style="font-weight:bold">@{{ username }}</span> to View Action<a href='
{{ config["BASE_URL"] }}{{ url_for("main.view_dashboard", **{ "view_name": view_name}) }}'>{{ display_name }}</a>.
<p>Action: {{ action }}</p>
</div>
Loading