mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba2fc55188 | ||
|
|
a6896c9b50 | ||
|
|
8dd74f310d | ||
|
|
44ed9e9ca6 | ||
|
|
c925407f05 | ||
|
|
622fc369d0 | ||
|
|
9580ad3934 | ||
|
|
b33c0810d5 | ||
|
|
8fbe639aa1 | ||
|
|
d7e2ec3b08 | ||
|
|
fdaca0e8a7 | ||
|
|
7959f903bb | ||
|
|
59eb91f28f | ||
|
|
64724d2a92 | ||
|
|
91a6d672fa | ||
|
|
50809476fa | ||
|
|
282ffb543c | ||
|
|
68fea480ae | ||
|
|
ec64ea8229 | ||
|
|
b13433e554 | ||
|
|
d9fd382cb2 | ||
|
|
4d324d885d | ||
|
|
af1a437523 | ||
|
|
77901ae1bc | ||
|
|
1aeff542e5 | ||
|
|
b81ad079ee | ||
|
|
044edcda07 | ||
|
|
3f7eb4528e | ||
|
|
0008f70552 | ||
|
|
2695715180 | ||
|
|
b3be1a561c | ||
|
|
d297f1a27b | ||
|
|
b513509b01 | ||
|
|
25744efc66 | ||
|
|
21e37366fb | ||
|
|
3f6a47c39d | ||
|
|
4dace0a32b | ||
|
|
7b6ca12744 | ||
|
|
da1b5a969c | ||
|
|
8e5d6eec6c | ||
|
|
92f1400a35 | ||
|
|
47f1938136 | ||
|
|
f226218b3a | ||
|
|
8f7fa0dea1 | ||
|
|
292b3c805d | ||
|
|
ded26f92af | ||
|
|
8cce7bbaf4 | ||
|
|
228b8c3ec7 | ||
|
|
2e298ce757 | ||
|
|
81daa9f0b0 | ||
|
|
713c8d9177 | ||
|
|
f571162eed | ||
|
|
19d2872943 | ||
|
|
0752b8bf7f | ||
|
|
c01097196a | ||
|
|
5f1bee018d | ||
|
|
8655b81618 | ||
|
|
1702e43373 | ||
|
|
a7d411f6ff | ||
|
|
6a84da0f96 | ||
|
|
79425f4490 | ||
|
|
2fcddea0fa | ||
|
|
ac1c8552e1 | ||
|
|
6a18eefe34 | ||
|
|
a43eedaf9f | ||
|
|
77bc24990e | ||
|
|
edbc79c89e | ||
|
|
527a090f1b | ||
|
|
370b86337f | ||
|
|
1ce3acdde0 | ||
|
|
1a72be323b | ||
|
|
bf252f22f2 | ||
|
|
937d92f686 | ||
|
|
5572957731 | ||
|
|
d2db5722b7 | ||
|
|
5404185a6c | ||
|
|
800f2dfbbb | ||
|
|
ed0b5410f6 | ||
|
|
ae72e262aa | ||
|
|
c4c7050c3f | ||
|
|
81e5227270 | ||
|
|
39319d9162 | ||
|
|
12206fa856 | ||
|
|
9d8c6e26f1 | ||
|
|
eb624672e6 | ||
|
|
1b026b5f08 | ||
|
|
095444610d |
@@ -2,7 +2,7 @@ name: Auto Release bot
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
types: [ closed ]
|
||||
branches:
|
||||
- main
|
||||
|
||||
@@ -12,7 +12,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
@@ -38,7 +37,11 @@ jobs:
|
||||
- run: git config --global user.name 'github-actions[bot]'
|
||||
- run: git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
|
||||
- name: Fetch tags
|
||||
run: git fetch --tags
|
||||
|
||||
- name: Run release-it
|
||||
id: release_step
|
||||
run: |
|
||||
git pull origin main
|
||||
pnpm exec release-it --ci
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
name: Publish Docker image for release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [ created ]
|
||||
push:
|
||||
tags:
|
||||
- "*.*.*"
|
||||
@@ -11,6 +13,14 @@ permissions:
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
|
||||
log-draft-tag:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Read draft tag
|
||||
run: |
|
||||
echo ${{ github.event.release.id }}
|
||||
|
||||
docker_publish:
|
||||
uses: ./.github/workflows/docker.yml
|
||||
with:
|
||||
@@ -18,12 +28,28 @@ jobs:
|
||||
secrets:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME_2 }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD_2 }}
|
||||
publish_release:
|
||||
needs: docker_publish
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Publish GitHub Release
|
||||
if: ${{ github.event.release.draft == true }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# gh release edit v${{ github.ref_name }} --draft=false
|
||||
run: |
|
||||
gh release edit ${{ github.event.release.id }} --draft=false
|
||||
|
||||
discord_notification:
|
||||
needs: docker_publish
|
||||
uses: ./.github/workflows/discord.yml
|
||||
with:
|
||||
discord_title: "New Release: ${{ github.ref_name }}"
|
||||
discord_title: "New Release: v${{ github.ref_name }}"
|
||||
discord_color: 3066993
|
||||
discord_footer: "Portabase"
|
||||
secrets:
|
||||
|
||||
+7
-5
@@ -1,16 +1,18 @@
|
||||
{
|
||||
"github": {
|
||||
"release": true,
|
||||
"draft": true,
|
||||
"tokenRef": "GITHUB_TOKEN",
|
||||
"update": true
|
||||
},
|
||||
"git": {
|
||||
"commit": true,
|
||||
"commitMessage": "chore: release v${version}",
|
||||
"requireCleanWorkingDir": true,
|
||||
"tag": true,
|
||||
"tagName": "${version}",
|
||||
"tagName": "v${version}",
|
||||
"push": true
|
||||
},
|
||||
"github": {
|
||||
"release": true,
|
||||
"tokenRef": "GITHUB_TOKEN"
|
||||
},
|
||||
"plugins": {
|
||||
"@release-it/conventional-changelog": {
|
||||
"preset": {
|
||||
|
||||
+1
-1
@@ -31,5 +31,5 @@ keywords:
|
||||
- web-ui
|
||||
- agent
|
||||
license: Apache-2.0
|
||||
version: 1.4.13
|
||||
version: 1.4.42
|
||||
date-released: '2026-03-02'
|
||||
|
||||
+1
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "portabase",
|
||||
"version": "1.4.13",
|
||||
"version": "1.4.42",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack -p 8887",
|
||||
@@ -50,7 +50,6 @@
|
||||
"@t3-oss/env-nextjs": "^0.13.10",
|
||||
"@tanstack/react-query": "^5.90.21",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"@types/express": "^5.0.6",
|
||||
"@types/nodemailer": "^6.4.23",
|
||||
"@types/ws": "^8.18.1",
|
||||
"@zenstackhq/runtime": "2.14.2",
|
||||
|
||||
Generated
-67
@@ -113,9 +113,6 @@ importers:
|
||||
'@tanstack/react-table':
|
||||
specifier: ^8.21.3
|
||||
version: 8.21.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@types/express':
|
||||
specifier: ^5.0.6
|
||||
version: 5.0.6
|
||||
'@types/nodemailer':
|
||||
specifier: ^6.4.23
|
||||
version: 6.4.23
|
||||
@@ -3143,12 +3140,6 @@ packages:
|
||||
'@tybys/wasm-util@0.10.1':
|
||||
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
|
||||
|
||||
'@types/body-parser@1.19.6':
|
||||
resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==}
|
||||
|
||||
'@types/connect@3.4.38':
|
||||
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
|
||||
|
||||
'@types/cors@2.8.19':
|
||||
resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==}
|
||||
|
||||
@@ -3191,15 +3182,6 @@ packages:
|
||||
'@types/estree@1.0.8':
|
||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
||||
|
||||
'@types/express-serve-static-core@5.1.1':
|
||||
resolution: {integrity: sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==}
|
||||
|
||||
'@types/express@5.0.6':
|
||||
resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==}
|
||||
|
||||
'@types/http-errors@2.0.5':
|
||||
resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==}
|
||||
|
||||
'@types/json-schema@7.0.15':
|
||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||
|
||||
@@ -3237,12 +3219,6 @@ packages:
|
||||
'@types/prismjs@1.26.6':
|
||||
resolution: {integrity: sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==}
|
||||
|
||||
'@types/qs@6.14.0':
|
||||
resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==}
|
||||
|
||||
'@types/range-parser@1.2.7':
|
||||
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
|
||||
|
||||
'@types/react-dom@19.0.4':
|
||||
resolution: {integrity: sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==}
|
||||
peerDependencies:
|
||||
@@ -3259,12 +3235,6 @@ packages:
|
||||
'@types/react@19.2.14':
|
||||
resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==}
|
||||
|
||||
'@types/send@1.2.1':
|
||||
resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==}
|
||||
|
||||
'@types/serve-static@2.2.0':
|
||||
resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==}
|
||||
|
||||
'@types/webpack@5.28.5':
|
||||
resolution: {integrity: sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==}
|
||||
|
||||
@@ -10490,15 +10460,6 @@ snapshots:
|
||||
tslib: 2.8.1
|
||||
optional: true
|
||||
|
||||
'@types/body-parser@1.19.6':
|
||||
dependencies:
|
||||
'@types/connect': 3.4.38
|
||||
'@types/node': 22.19.11
|
||||
|
||||
'@types/connect@3.4.38':
|
||||
dependencies:
|
||||
'@types/node': 22.19.11
|
||||
|
||||
'@types/cors@2.8.19':
|
||||
dependencies:
|
||||
'@types/node': 22.19.11
|
||||
@@ -10543,21 +10504,6 @@ snapshots:
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
||||
'@types/express-serve-static-core@5.1.1':
|
||||
dependencies:
|
||||
'@types/node': 22.19.11
|
||||
'@types/qs': 6.14.0
|
||||
'@types/range-parser': 1.2.7
|
||||
'@types/send': 1.2.1
|
||||
|
||||
'@types/express@5.0.6':
|
||||
dependencies:
|
||||
'@types/body-parser': 1.19.6
|
||||
'@types/express-serve-static-core': 5.1.1
|
||||
'@types/serve-static': 2.2.0
|
||||
|
||||
'@types/http-errors@2.0.5': {}
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
|
||||
'@types/json5@0.0.29': {}
|
||||
@@ -10598,10 +10544,6 @@ snapshots:
|
||||
|
||||
'@types/prismjs@1.26.6': {}
|
||||
|
||||
'@types/qs@6.14.0': {}
|
||||
|
||||
'@types/range-parser@1.2.7': {}
|
||||
|
||||
'@types/react-dom@19.0.4(@types/react@19.0.10)':
|
||||
dependencies:
|
||||
'@types/react': 19.0.10
|
||||
@@ -10618,15 +10560,6 @@ snapshots:
|
||||
dependencies:
|
||||
csstype: 3.2.3
|
||||
|
||||
'@types/send@1.2.1':
|
||||
dependencies:
|
||||
'@types/node': 22.19.11
|
||||
|
||||
'@types/serve-static@2.2.0':
|
||||
dependencies:
|
||||
'@types/http-errors': 2.0.5
|
||||
'@types/node': 22.19.11
|
||||
|
||||
'@types/webpack@5.28.5(esbuild@0.25.10)':
|
||||
dependencies:
|
||||
'@types/node': 22.19.11
|
||||
|
||||
+232
-53
@@ -1,62 +1,241 @@
|
||||
"use client"
|
||||
import {Eye} from "lucide-react";
|
||||
|
||||
import {useState} from "react";
|
||||
"use client";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger
|
||||
AlertCircle,
|
||||
Braces,
|
||||
Database,
|
||||
ExternalLink,
|
||||
Eye,
|
||||
Hash,
|
||||
Server,
|
||||
Sparkles,
|
||||
} from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {Separator} from "@/components/ui/separator";
|
||||
import {NotificationLogWithRelations} from "@/db/services/notification-log";
|
||||
import type { NotificationLogWithRelations } from "@/db/services/notification-log";
|
||||
|
||||
type NotificationLogModalProps = {
|
||||
notificationLog: NotificationLogWithRelations;
|
||||
}
|
||||
notificationLog: NotificationLogWithRelations;
|
||||
};
|
||||
|
||||
export const NotificationLogModal = ({notificationLog}: NotificationLogModalProps) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const getTroubleshootingForError = (errorMsg?: any) => {
|
||||
if (!errorMsg || String(errorMsg).toLowerCase() === "null") return null;
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" onClick={() => setOpen(true)} className="relative">
|
||||
<Eye/>
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Notification details</DialogTitle>
|
||||
<DialogDescription>
|
||||
Details of the notification sent
|
||||
</DialogDescription>
|
||||
<Separator className="mt-3 mb-3"/>
|
||||
const msg = String(errorMsg).toLowerCase();
|
||||
|
||||
<div className="space-y-2 mb-4">
|
||||
<div>
|
||||
<span className="font-semibold">Title:</span>{" "}
|
||||
<span>{notificationLog.content.title}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-semibold">Message:</span>{" "}
|
||||
<span>{notificationLog.content.message}</span>
|
||||
</div>
|
||||
if (msg.includes("database connection") || msg.includes("agent")) {
|
||||
return {
|
||||
title: "Agent Connection Issue",
|
||||
resolution:
|
||||
"It appears the agent cannot reach the database. Please ensure that your agent is actively running, your PostgreSQL credentials are correct, and port 5432 is open on your firewall.",
|
||||
docLink:
|
||||
"https://portabase.io/docs/agent/troubleshooting/agent-connection",
|
||||
};
|
||||
}
|
||||
|
||||
if (msg.includes("timeout")) {
|
||||
return {
|
||||
title: "Timeout",
|
||||
resolution:
|
||||
"The agent is taking too long to respond. This could be due to high server load, network issues, or a large database.",
|
||||
docLink: "https://portabase.io/docs/agent/troubleshooting/timeout",
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
title: "Unexpected Execution Error",
|
||||
resolution:
|
||||
"An unexpected error occurred during execution. Please review the raw system logs or contact support if the issue persists.",
|
||||
docLink: "https://discord.gg/Wgv7xZ8fWJ",
|
||||
};
|
||||
};
|
||||
|
||||
const getIconForKey = (key: string, value: any) => {
|
||||
const isActualError =
|
||||
key.toLowerCase().includes("error") &&
|
||||
value !== null &&
|
||||
String(value).toLowerCase() !== "null";
|
||||
|
||||
if (key.toLowerCase().includes("id"))
|
||||
return <Hash className="w-3.5 h-3.5 text-muted-foreground" />;
|
||||
if (key.toLowerCase().includes("host"))
|
||||
return <Server className="w-3.5 h-3.5 text-muted-foreground" />;
|
||||
if (isActualError)
|
||||
return <AlertCircle className="w-3.5 h-3.5 text-destructive" />;
|
||||
return <Database className="w-3.5 h-3.5 text-muted-foreground" />;
|
||||
};
|
||||
|
||||
export const NotificationLogModal = ({
|
||||
notificationLog,
|
||||
}: NotificationLogModalProps) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
// TODO : to be fixed
|
||||
// @ts-ignore
|
||||
const payloadError = notificationLog.payload?.error;
|
||||
const troubleshooting = getTroubleshootingForError(payloadError);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setOpen(true)}
|
||||
className="relative"
|
||||
>
|
||||
<Eye className="w-4 h-4" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-xl bg-background">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Notification Details</DialogTitle>
|
||||
<DialogDescription>Execution logs and payload data</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-4 mt-2 max-h-[70vh] overflow-y-auto px-1 pb-2">
|
||||
<div className="relative border rounded-xl bg-card shadow-sm flex flex-col">
|
||||
<div className="bg-primary/5 border-b px-4 py-2.5 flex items-center gap-2 rounded-t-xl">
|
||||
<div className="p-1 bg-primary/10 rounded-md">
|
||||
<Database className="w-4 h-4 text-primary" />
|
||||
</div>
|
||||
<span className="font-semibold text-sm text-primary">
|
||||
Event Trigger
|
||||
</span>
|
||||
</div>
|
||||
<div className="p-4 flex flex-col gap-4">
|
||||
<div className="flex flex-col sm:flex-row sm:items-start justify-between gap-1 sm:gap-4">
|
||||
<span className="text-xs font-medium text-muted-foreground min-w-20 pt-0.5">
|
||||
Title
|
||||
</span>
|
||||
<span className="text-sm sm:text-right flex-1 wrap-break-words">
|
||||
{notificationLog.content.title}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col sm:flex-row sm:items-start justify-between gap-1 sm:gap-4">
|
||||
<span className="text-xs font-medium text-muted-foreground min-w-20 pt-0.5">
|
||||
Message
|
||||
</span>
|
||||
<span className="text-sm sm:text-right flex-1 wrap-break-word text-muted-foreground">
|
||||
{notificationLog.content.message}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{notificationLog.payload && (
|
||||
<div className="absolute -bottom-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-primary rounded-full border-2 border-background z-10" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="w-px h-6 bg-border mx-auto -my-4 relative z-0" />
|
||||
|
||||
{notificationLog.payload &&
|
||||
Object.keys(notificationLog.payload).length > 0 && (
|
||||
<div className="relative border rounded-xl bg-card shadow-sm flex flex-col">
|
||||
<div className="absolute -top-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-primary rounded-full border-2 border-background z-10" />
|
||||
|
||||
<div className="bg-primary/5 border-b px-4 py-2.5 flex items-center justify-between rounded-t-xl">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1 bg-primary/10 rounded-md">
|
||||
<Braces className="w-4 h-4 text-primary" />
|
||||
</div>
|
||||
<span className="font-semibold text-sm text-primary">
|
||||
JSON Payload
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{notificationLog.payload && (
|
||||
<>
|
||||
<Separator className="mb-3" />
|
||||
<div className="text-sm font-mono bg-gray-100 dark:bg-gray-800 dark:text-gray-200 p-4 rounded-md overflow-auto">
|
||||
{JSON.stringify(notificationLog.payload, null, 2)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</DialogHeader>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
<div className="flex flex-col">
|
||||
{Object.entries(notificationLog.payload).map(
|
||||
([key, value], index, arr) => {
|
||||
const isActualError =
|
||||
key === "error" &&
|
||||
value !== null &&
|
||||
String(value).toLowerCase() !== "null";
|
||||
|
||||
return (
|
||||
<div
|
||||
key={key}
|
||||
className={`flex flex-col sm:flex-row sm:items-center justify-between gap-2 px-4 py-3 hover:bg-muted/50 transition-colors ${
|
||||
index !== arr.length - 1
|
||||
? "border-b border-border/50"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-2 min-w-[150px]">
|
||||
{getIconForKey(key, value)}
|
||||
<span className="text-sm font-medium">{key}</span>
|
||||
</div>
|
||||
<div className="flex-1 sm:text-right">
|
||||
{isActualError ? (
|
||||
<span className="inline-flex items-center px-2 py-1 rounded-md bg-destructive/10 text-destructive text-xs font-mono break-all">
|
||||
{String(value)}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-sm text-muted-foreground font-mono bg-muted px-2 py-1 rounded-md break-all">
|
||||
{String(value)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
|
||||
{troubleshooting && (
|
||||
<div className="absolute -bottom-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-primary rounded-full border-2 border-background z-10" />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{troubleshooting && (
|
||||
<>
|
||||
<div className="w-px h-6 bg-border mx-auto -my-4 relative z-0" />
|
||||
|
||||
<div className="relative border border-destructive/20 rounded-xl bg-gradient-to-b from-destructive/5 to-transparent shadow-sm flex flex-col">
|
||||
<div className="absolute -top-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-destructive rounded-full border-2 border-background z-10" />
|
||||
|
||||
<div className="bg-destructive/10 border-b border-destructive/10 px-4 py-2.5 flex items-center justify-between rounded-t-xl">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1 bg-destructive/20 rounded-md">
|
||||
<Sparkles className="w-4 h-4 text-destructive" />
|
||||
</div>
|
||||
<span className="font-semibold text-sm text-destructive">
|
||||
Suggested Resolution
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-4 flex flex-col gap-2">
|
||||
<h4 className="text-sm font-semibold text-foreground">
|
||||
{troubleshooting.title}
|
||||
</h4>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed">
|
||||
{troubleshooting.resolution}
|
||||
</p>
|
||||
<div className="mt-2">
|
||||
<a
|
||||
href={troubleshooting.docLink}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-flex items-center gap-1.5 text-xs font-semibold text-destructive hover:text-destructive/80 transition-colors"
|
||||
>
|
||||
Read the documentation{" "}
|
||||
<ExternalLink className="w-3.5 h-3.5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user