From ee1ea443465745ab38d6c839fa63045a26002a85 Mon Sep 17 00:00:00 2001 From: Furkan Pehlivan <65170388+pehlicd@users.noreply.github.com> Date: Sun, 21 Apr 2024 09:13:17 +0200 Subject: [PATCH] feat: add last updated timestamp to mapping ui (#1115) Signed-off-by: Tal Co-authored-by: Tal Co-authored-by: Tal --- keep-ui/app/mapping/mapping.tsx | 1 + keep-ui/app/mapping/models.tsx | 2 ++ keep-ui/app/mapping/rules-table.tsx | 45 ++++++++++++++++++++++++++++- keep/api/core/db.py | 20 +++++++++++++ keep/api/models/db/mapping.py | 4 +++ keep/api/routes/mapping.py | 3 ++ 6 files changed, 74 insertions(+), 1 deletion(-) diff --git a/keep-ui/app/mapping/mapping.tsx b/keep-ui/app/mapping/mapping.tsx index bce8e0e0e..52a57f09f 100644 --- a/keep-ui/app/mapping/mapping.tsx +++ b/keep-ui/app/mapping/mapping.tsx @@ -7,6 +7,7 @@ import { MdWarning } from "react-icons/md"; import Loading from "app/loading"; import {MappingRule} from "./models"; import {useState} from "react"; + export default function Mapping() { const { data: mappings, isLoading } = useMappings(); diff --git a/keep-ui/app/mapping/models.tsx b/keep-ui/app/mapping/models.tsx index 7eb3a1c2e..1caa6f050 100644 --- a/keep-ui/app/mapping/models.tsx +++ b/keep-ui/app/mapping/models.tsx @@ -7,6 +7,8 @@ export interface MappingRule { file_name?: string; created_by?: string; created_at: Date; + updated_by?: string; + last_updated_at: Date; disabled: boolean; override: boolean; condition?: string; diff --git a/keep-ui/app/mapping/rules-table.tsx b/keep-ui/app/mapping/rules-table.tsx index 5b19d2802..feec54daa 100644 --- a/keep-ui/app/mapping/rules-table.tsx +++ b/keep-ui/app/mapping/rules-table.tsx @@ -14,13 +14,14 @@ import { createColumnHelper, flexRender, getCoreRowModel, - useReactTable, + useReactTable, ExpandedState, } from "@tanstack/react-table"; import { MdRemoveCircle, MdModeEdit } from "react-icons/md"; import { useSession } from "next-auth/react"; import { getApiURL } from "utils/apiUrl"; import { useMappings } from "utils/hooks/useMappingRules"; import { toast } from "react-toastify"; +import {useState} from "react"; const columnHelper = createColumnHelper(); @@ -32,6 +33,7 @@ interface Props { export default function RulesTable({ mappings, editCallback }: Props) { const { data: session } = useSession(); const { mutate } = useMappings(); + const [expanded, setExpanded] = useState({}); const columns = [ columnHelper.display({ @@ -100,7 +102,9 @@ export default function RulesTable({ mappings, editCallback }: Props) { const table = useReactTable({ columns, data: mappings.sort((a, b) => b.priority - a.priority), + state: { expanded }, getCoreRowModel: getCoreRowModel(), + onExpandedChange: setExpanded, }); const deleteRule = (ruleId: number) => { @@ -148,9 +152,11 @@ export default function RulesTable({ mappings, editCallback }: Props) { {table.getRowModel().rows.map((row) => ( + <> row.toggleExpanded()} > {row.getVisibleCells().map((cell) => ( @@ -158,6 +164,43 @@ export default function RulesTable({ mappings, editCallback }: Props) { ))} + {row.getIsExpanded() && ( + + +
+
+ Created At: + + {new Date( + row.original.created_at + "Z" + ).toLocaleString()} + +
+
+ Created By: + {row.original.created_by} +
+ {row.original.last_updated_at && ( + <> +
+ Updated At: + + {new Date( + row.original.last_updated_at + "Z" + ).toLocaleString()} + +
+
+ Updated By: + {row.original.updated_by} +
+ + )} +
+
+
+ )} + ))}
diff --git a/keep/api/core/db.py b/keep/api/core/db.py index f51368151..8ab290553 100644 --- a/keep/api/core/db.py +++ b/keep/api/core/db.py @@ -187,6 +187,26 @@ def create_db_and_tables(): logger.exception("Failed to migrate rule table") pass logger.info("Migrated Rule table") + # add updated_by and last_updated_at to the mapping rule table + logger.info("Migrating MappingRule table") + try: + if session.bind.dialect.name == "postgresql": + session.exec("ALTER TABLE mappingrule ADD COLUMN updated_by VARCHAR(255);") + session.exec("ALTER TABLE mappingrule ADD COLUMN last_updated_at TIMESTAMP;") + elif session.bind.dialect.name == "mssql": + session.exec("ALTER TABLE mappingrule ADD updated_by NVARCHAR(255);") + session.exec("ALTER TABLE mappingrule ADD last_updated_at DATETIME;") + else: + session.exec("ALTER TABLE mappingrule ADD COLUMN updated_by VARCHAR(255);") + session.exec("ALTER TABLE mappingrule ADD COLUMN last_updated_at DATETIME;") + except Exception as e: + # that's ok + if "Duplicate column name" in str(e): + pass + # else, log + else: + logger.exception("Failed to migrate mapping rule table") + pass session.commit() logger.info("Migrated succesfully") except Exception: diff --git a/keep/api/models/db/mapping.py b/keep/api/models/db/mapping.py index d1acb2add..394951a97 100644 --- a/keep/api/models/db/mapping.py +++ b/keep/api/models/db/mapping.py @@ -25,6 +25,8 @@ class MappingRule(SQLModel, table=True): sa_column=Column(JSON), nullable=False, ) # max_length=204800) + updated_by: Optional[str] = Field(max_length=255, default=None) + last_updated_at: datetime = Field(default_factory=datetime.utcnow) class MappRuleDtoBase(BaseModel): @@ -40,6 +42,8 @@ class MappingRuleDtoOut(MappRuleDtoBase, extra="ignore"): created_by: Optional[str] created_at: datetime attributes: list[str] = [] + updated_by: Optional[str] | None + last_updated_at: Optional[datetime] | None class MappingRuleDtoIn(MappRuleDtoBase): diff --git a/keep/api/routes/mapping.py b/keep/api/routes/mapping.py index ce0e3f3a3..6551c99bc 100644 --- a/keep/api/routes/mapping.py +++ b/keep/api/routes/mapping.py @@ -1,3 +1,4 @@ +import datetime import logging from fastapi import APIRouter, Depends, HTTPException @@ -108,6 +109,8 @@ def update_rule( existing_rule.matchers = rule.matchers existing_rule.file_name = rule.file_name existing_rule.priority = rule.priority + existing_rule.updated_by = authenticated_entity.email + existing_rule.last_updated_at = datetime.datetime.now(tz=datetime.timezone.utc) if rule.rows is not None: existing_rule.rows = rule.rows session.commit()