feat: add error filtering option to InboxSidebar, allowing users to filter notifications by error types, and update translations for new filter option in multiple languages

This commit is contained in:
Anish Sarkar 2026-03-06 17:29:42 +05:30
parent d03f938fcd
commit 1aa2c8a334
6 changed files with 52 additions and 2 deletions

View file

@ -137,7 +137,7 @@ function getConnectorTypeDisplayName(connectorType: string): string {
} }
type InboxTab = "comments" | "status"; type InboxTab = "comments" | "status";
type InboxFilter = "all" | "unread"; type InboxFilter = "all" | "unread" | "errors";
// Tab-specific data source with independent pagination // Tab-specific data source with independent pagination
interface TabDataSource { interface TabDataSource {
@ -399,6 +399,12 @@ export function InboxSidebar({
if (activeFilter === "unread") { if (activeFilter === "unread") {
items = items.filter((item) => !item.read); items = items.filter((item) => !item.read);
} else if (activeFilter === "errors") {
items = items.filter((item) => {
if (item.type === "page_limit_exceeded") return true;
const meta = item.metadata as Record<string, unknown> | undefined;
return typeof meta?.status === "string" && meta.status === "failed";
});
} }
return items; return items;
@ -712,6 +718,27 @@ export function InboxSidebar({
</span> </span>
{activeFilter === "unread" && <Check className="h-4 w-4" />} {activeFilter === "unread" && <Check className="h-4 w-4" />}
</button> </button>
{activeTab === "status" && (
<button
type="button"
onClick={() => {
setActiveFilter("errors");
setFilterDrawerOpen(false);
}}
className={cn(
"flex w-full items-center justify-between rounded-lg px-3 py-2.5 text-sm transition-colors",
activeFilter === "errors"
? "bg-primary/10 text-primary"
: "hover:bg-muted"
)}
>
<span className="flex items-center gap-2">
<AlertCircle className="h-4 w-4" />
<span>{t("errors_only") || "Errors only"}</span>
</span>
{activeFilter === "errors" && <Check className="h-4 w-4" />}
</button>
)}
</div> </div>
</div> </div>
{/* Sources section - only for status tab */} {/* Sources section - only for status tab */}
@ -815,6 +842,18 @@ export function InboxSidebar({
</span> </span>
{activeFilter === "unread" && <Check className="h-4 w-4" />} {activeFilter === "unread" && <Check className="h-4 w-4" />}
</DropdownMenuItem> </DropdownMenuItem>
{activeTab === "status" && (
<DropdownMenuItem
onClick={() => setActiveFilter("errors")}
className="flex items-center justify-between"
>
<span className="flex items-center gap-2">
<AlertCircle className="h-4 w-4" />
<span>{t("errors_only") || "Errors only"}</span>
</span>
{activeFilter === "errors" && <Check className="h-4 w-4" />}
</DropdownMenuItem>
)}
{activeTab === "status" && statusSourceOptions.length > 0 && ( {activeTab === "status" && statusSourceOptions.length > 0 && (
<> <>
<DropdownMenuLabel className="text-xs text-muted-foreground/80 font-normal mt-2"> <DropdownMenuLabel className="text-xs text-muted-foreground/80 font-normal mt-2">
@ -949,7 +988,13 @@ export function InboxSidebar({
<Tabs <Tabs
value={activeTab} value={activeTab}
onValueChange={(value) => setActiveTab(value as InboxTab)} onValueChange={(value) => {
const tab = value as InboxTab;
setActiveTab(tab);
if (tab !== "status" && activeFilter === "errors") {
setActiveFilter("all");
}
}}
className="shrink-0 mx-4" className="shrink-0 mx-4"
> >
<TabsList className="w-full h-auto p-0 bg-transparent rounded-none border-b"> <TabsList className="w-full h-auto p-0 bg-transparent rounded-none border-b">

View file

@ -719,6 +719,7 @@
"filter": "Filter", "filter": "Filter",
"all": "All", "all": "All",
"unread": "Unread", "unread": "Unread",
"errors_only": "Errors only",
"connectors": "Connectors", "connectors": "Connectors",
"all_connectors": "All connectors", "all_connectors": "All connectors",
"sources": "Sources", "sources": "Sources",

View file

@ -719,6 +719,7 @@
"filter": "Filtrar", "filter": "Filtrar",
"all": "Todo", "all": "Todo",
"unread": "No leído", "unread": "No leído",
"errors_only": "Solo errores",
"connectors": "Conectores", "connectors": "Conectores",
"all_connectors": "Todos los conectores", "all_connectors": "Todos los conectores",
"sources": "Fuentes", "sources": "Fuentes",

View file

@ -719,6 +719,7 @@
"filter": "फ़िल्टर", "filter": "फ़िल्टर",
"all": "सभी", "all": "सभी",
"unread": "अपठित", "unread": "अपठित",
"errors_only": "केवल त्रुटियाँ",
"connectors": "कनेक्टर", "connectors": "कनेक्टर",
"all_connectors": "सभी कनेक्टर", "all_connectors": "सभी कनेक्टर",
"sources": "स्रोत", "sources": "स्रोत",

View file

@ -719,6 +719,7 @@
"filter": "Filtrar", "filter": "Filtrar",
"all": "Tudo", "all": "Tudo",
"unread": "Não lido", "unread": "Não lido",
"errors_only": "Apenas erros",
"connectors": "Conectores", "connectors": "Conectores",
"all_connectors": "Todos os conectores", "all_connectors": "Todos os conectores",
"sources": "Fontes", "sources": "Fontes",

View file

@ -703,6 +703,7 @@
"filter": "筛选", "filter": "筛选",
"all": "全部", "all": "全部",
"unread": "未读", "unread": "未读",
"errors_only": "仅错误",
"connectors": "连接器", "connectors": "连接器",
"all_connectors": "所有连接器", "all_connectors": "所有连接器",
"sources": "来源", "sources": "来源",