mirror of
https://github.com/databasus/databasus.git
synced 2026-04-06 00:32:03 +02:00
FEATURE (notifiers): Add webhook notifier
This commit is contained in:
@@ -5,4 +5,5 @@ type NotifierType string
|
||||
const (
|
||||
NotifierTypeEmail NotifierType = "EMAIL"
|
||||
NotifierTypeTelegram NotifierType = "TELEGRAM"
|
||||
NotifierTypeWebhook NotifierType = "WEBHOOK"
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"postgresus-backend/internal/features/notifiers/notifiers/email_notifier"
|
||||
telegram_notifier "postgresus-backend/internal/features/notifiers/notifiers/telegram"
|
||||
webhook_notifier "postgresus-backend/internal/features/notifiers/notifiers/webhook"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
@@ -18,6 +19,7 @@ type Notifier struct {
|
||||
// specific notifier
|
||||
TelegramNotifier *telegram_notifier.TelegramNotifier `json:"telegramNotifier" gorm:"foreignKey:NotifierID"`
|
||||
EmailNotifier *email_notifier.EmailNotifier `json:"emailNotifier" gorm:"foreignKey:NotifierID"`
|
||||
WebhookNotifier *webhook_notifier.WebhookNotifier `json:"webhookNotifier" gorm:"foreignKey:NotifierID"`
|
||||
}
|
||||
|
||||
func (n *Notifier) TableName() string {
|
||||
@@ -34,6 +36,7 @@ func (n *Notifier) Validate() error {
|
||||
|
||||
func (n *Notifier) Send(heading string, message string) error {
|
||||
err := n.getSpecificNotifier().Send(heading, message)
|
||||
|
||||
if err != nil {
|
||||
lastSendError := err.Error()
|
||||
n.LastSendError = &lastSendError
|
||||
@@ -50,6 +53,8 @@ func (n *Notifier) getSpecificNotifier() NotificationSender {
|
||||
return n.TelegramNotifier
|
||||
case NotifierTypeEmail:
|
||||
return n.EmailNotifier
|
||||
case NotifierTypeWebhook:
|
||||
return n.WebhookNotifier
|
||||
default:
|
||||
panic("unknown notifier type: " + string(n.NotifierType))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package webhook_notifier
|
||||
|
||||
type WebhookMethod string
|
||||
|
||||
const (
|
||||
WebhookMethodPOST WebhookMethod = "POST"
|
||||
WebhookMethodGET WebhookMethod = "GET"
|
||||
)
|
||||
106
backend/internal/features/notifiers/notifiers/webhook/model.go
Normal file
106
backend/internal/features/notifiers/notifiers/webhook/model.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package webhook_notifier
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"postgresus-backend/internal/util/logger"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
var log = logger.GetLogger()
|
||||
|
||||
type WebhookNotifier struct {
|
||||
NotifierID uuid.UUID `json:"notifierId" gorm:"primaryKey;column:notifier_id"`
|
||||
WebhookURL string `json:"webhookUrl" gorm:"not null;column:webhook_url"`
|
||||
WebhookMethod WebhookMethod `json:"webhookMethod" gorm:"not null;column:webhook_method"`
|
||||
}
|
||||
|
||||
func (t *WebhookNotifier) TableName() string {
|
||||
return "webhook_notifiers"
|
||||
}
|
||||
|
||||
func (t *WebhookNotifier) Validate() error {
|
||||
if t.WebhookURL == "" {
|
||||
return errors.New("webhook URL is required")
|
||||
}
|
||||
|
||||
if t.WebhookMethod == "" {
|
||||
return errors.New("webhook method is required")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *WebhookNotifier) Send(heading string, message string) error {
|
||||
switch t.WebhookMethod {
|
||||
case WebhookMethodGET:
|
||||
reqURL := fmt.Sprintf("%s?heading=%s&message=%s",
|
||||
t.WebhookURL,
|
||||
url.QueryEscape(heading),
|
||||
url.QueryEscape(message),
|
||||
)
|
||||
|
||||
resp, err := http.Get(reqURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to send GET webhook: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
if cerr := resp.Body.Close(); cerr != nil {
|
||||
log.Error("failed to close response body", "error", cerr)
|
||||
}
|
||||
}()
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
return fmt.Errorf(
|
||||
"webhook GET returned status: %s, body: %s",
|
||||
resp.Status,
|
||||
string(body),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
case WebhookMethodPOST:
|
||||
payload := map[string]string{
|
||||
"heading": heading,
|
||||
"message": message,
|
||||
}
|
||||
|
||||
body, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal webhook payload: %w", err)
|
||||
}
|
||||
|
||||
resp, err := http.Post(t.WebhookURL, "application/json", bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to send POST webhook: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if cerr := resp.Body.Close(); cerr != nil {
|
||||
log.Error("failed to close response body", "error", cerr)
|
||||
}
|
||||
}()
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
return fmt.Errorf(
|
||||
"webhook POST returned status: %s, body: %s",
|
||||
resp.Status,
|
||||
string(body),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unsupported webhook method: %s", t.WebhookMethod)
|
||||
}
|
||||
}
|
||||
@@ -22,17 +22,21 @@ func (r *NotifierRepository) Save(notifier *Notifier) error {
|
||||
if notifier.EmailNotifier != nil {
|
||||
notifier.EmailNotifier.NotifierID = notifier.ID
|
||||
}
|
||||
case NotifierTypeWebhook:
|
||||
if notifier.WebhookNotifier != nil {
|
||||
notifier.WebhookNotifier.NotifierID = notifier.ID
|
||||
}
|
||||
}
|
||||
|
||||
if notifier.ID == uuid.Nil {
|
||||
if err := tx.Create(notifier).
|
||||
Omit("TelegramNotifier", "EmailNotifier").
|
||||
Omit("TelegramNotifier", "EmailNotifier", "WebhookNotifier").
|
||||
Error; err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := tx.Save(notifier).
|
||||
Omit("TelegramNotifier", "EmailNotifier").
|
||||
Omit("TelegramNotifier", "EmailNotifier", "WebhookNotifier").
|
||||
Error; err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -53,6 +57,13 @@ func (r *NotifierRepository) Save(notifier *Notifier) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case NotifierTypeWebhook:
|
||||
if notifier.WebhookNotifier != nil {
|
||||
notifier.WebhookNotifier.NotifierID = notifier.ID // Ensure ID is set
|
||||
if err := tx.Save(notifier.WebhookNotifier).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -66,6 +77,7 @@ func (r *NotifierRepository) FindByID(id uuid.UUID) (*Notifier, error) {
|
||||
GetDb().
|
||||
Preload("TelegramNotifier").
|
||||
Preload("EmailNotifier").
|
||||
Preload("WebhookNotifier").
|
||||
Where("id = ?", id).
|
||||
First(¬ifier).Error; err != nil {
|
||||
return nil, err
|
||||
@@ -81,6 +93,7 @@ func (r *NotifierRepository) FindByUserID(userID uuid.UUID) ([]*Notifier, error)
|
||||
GetDb().
|
||||
Preload("TelegramNotifier").
|
||||
Preload("EmailNotifier").
|
||||
Preload("WebhookNotifier").
|
||||
Where("user_id = ?", userID).
|
||||
Find(¬ifiers).Error; err != nil {
|
||||
return nil, err
|
||||
@@ -105,6 +118,12 @@ func (r *NotifierRepository) Delete(notifier *Notifier) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case NotifierTypeWebhook:
|
||||
if notifier.WebhookNotifier != nil {
|
||||
if err := tx.Delete(notifier.WebhookNotifier).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the main notifier
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
|
||||
-- Create webhook notifiers table
|
||||
CREATE TABLE webhook_notifiers (
|
||||
notifier_id UUID PRIMARY KEY,
|
||||
webhook_url TEXT NOT NULL,
|
||||
webhook_method TEXT NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE webhook_notifiers
|
||||
ADD CONSTRAINT fk_webhook_notifiers_notifier
|
||||
FOREIGN KEY (notifier_id)
|
||||
REFERENCES notifiers (id)
|
||||
ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
|
||||
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
|
||||
DROP TABLE IF EXISTS webhook_notifiers;
|
||||
|
||||
-- +goose StatementEnd
|
||||
19
frontend/public/icons/notifiers/webhook.svg
Normal file
19
frontend/public/icons/notifiers/webhook.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg version="1.1" baseProfile="tiny" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="800px" height="800px" viewBox="0 0 24 24" overflow="visible" xml:space="preserve">
|
||||
<g >
|
||||
<rect y="0" fill="none" width="24" height="24"/>
|
||||
<g transform="translate(1.000000, 8.000000)">
|
||||
<path fill-rule="evenodd" fill="#5C85DE" d="M2-1.9c-1.1,0-2.3,1.1-2.3,2.2V10H2V5.5h2.2V10h2.2V0.3c0-1.1-1.1-2.2-2.3-2.2H2
|
||||
L2-1.9z M2,3.2v-3h2.2v3H2L2,3.2z"/>
|
||||
<path fill-rule="evenodd" fill="#5C85DE" d="M10.3-2C9.1-2,8-0.9,8,0.2V10l2.2,0V5.5h2.2c1.1,0,2.3-1.1,2.3-2.2l0-3
|
||||
c0-1.1-1.1-2.2-2.3-2.2H10.3L10.3-2z M10.2,3.2v-3h2.2v3H10.2L10.2,3.2z"/>
|
||||
<polygon fill-rule="evenodd" fill="#5C85DE" points="18.5,0.3 18.5,7.8 16.2,7.8 16.2,10 23,10 23,7.8 20.8,7.8 20.8,0.3 23,0.3
|
||||
23,-1.9 16.2,-1.9 16.2,0.3 "/>
|
||||
<polygon fill-rule="evenodd" fill="#3367D6" points="2,5.5 2,3.2 3.5,3.2 "/>
|
||||
<polygon fill-rule="evenodd" fill="#3367D6" points="10.2,5.5 10.2,3.2 11.5,3.2 "/>
|
||||
<polygon fill-rule="evenodd" fill="#3367D6" points="18.5,1.8 18.5,1.8 18.5,0.3 20.8,0.3 "/>
|
||||
</g>
|
||||
</g>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -2,4 +2,6 @@ export { notifierApi } from './api/notifierApi';
|
||||
export type { Notifier } from './models/Notifier';
|
||||
export type { EmailNotifier } from './models/EmailNotifier';
|
||||
export type { TelegramNotifier } from './models/TelegramNotifier';
|
||||
export type { WebhookNotifier } from './models/WebhookNotifier';
|
||||
export { WebhookMethod } from './models/WebhookMethod';
|
||||
export { NotifierType } from './models/NotifierType';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { EmailNotifier } from './EmailNotifier';
|
||||
import type { NotifierType } from './NotifierType';
|
||||
import type { TelegramNotifier } from './TelegramNotifier';
|
||||
import type { WebhookNotifier } from './WebhookNotifier';
|
||||
|
||||
export interface Notifier {
|
||||
id: string;
|
||||
@@ -11,4 +12,5 @@ export interface Notifier {
|
||||
// specific notifier
|
||||
telegramNotifier?: TelegramNotifier;
|
||||
emailNotifier?: EmailNotifier;
|
||||
webhookNotifier?: WebhookNotifier;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export enum NotifierType {
|
||||
EMAIL = 'EMAIL',
|
||||
TELEGRAM = 'TELEGRAM',
|
||||
WEBHOOK = 'WEBHOOK',
|
||||
}
|
||||
|
||||
4
frontend/src/entity/notifiers/models/WebhookMethod.ts
Normal file
4
frontend/src/entity/notifiers/models/WebhookMethod.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export enum WebhookMethod {
|
||||
POST = 'POST',
|
||||
GET = 'GET',
|
||||
}
|
||||
6
frontend/src/entity/notifiers/models/WebhookNotifier.ts
Normal file
6
frontend/src/entity/notifiers/models/WebhookNotifier.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { WebhookMethod } from './WebhookMethod';
|
||||
|
||||
export interface WebhookNotifier {
|
||||
webhookUrl: string;
|
||||
webhookMethod: WebhookMethod;
|
||||
}
|
||||
@@ -6,6 +6,8 @@ export const getNotifierLogoFromType = (type: NotifierType) => {
|
||||
return '/icons/notifiers/email.svg';
|
||||
case NotifierType.TELEGRAM:
|
||||
return '/icons/notifiers/telegram.svg';
|
||||
case NotifierType.WEBHOOK:
|
||||
return '/icons/notifiers/webhook.svg';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ export const getNotifierNameFromType = (type: NotifierType) => {
|
||||
return 'Email';
|
||||
case NotifierType.TELEGRAM:
|
||||
return 'Telegram';
|
||||
case NotifierType.WEBHOOK:
|
||||
return 'Webhook';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import { Button, Input, Select } from 'antd';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { type Notifier, NotifierType, notifierApi } from '../../../../entity/notifiers';
|
||||
import {
|
||||
type Notifier,
|
||||
NotifierType,
|
||||
WebhookMethod,
|
||||
notifierApi,
|
||||
} from '../../../../entity/notifiers';
|
||||
import { getNotifierLogoFromType } from '../../../../entity/notifiers/models/getNotifierLogoFromType';
|
||||
import { ToastHelper } from '../../../../shared/toast';
|
||||
import { EditEmailNotifierComponent } from './notifiers/EditEmailNotifierComponent';
|
||||
import { EditTelegramNotifierComponent } from './notifiers/EditTelegramNotifierComponent';
|
||||
import { EditWebhookNotifierComponent } from './notifiers/EditWebhookNotifierComponent';
|
||||
|
||||
interface Props {
|
||||
isShowClose: boolean;
|
||||
@@ -88,6 +95,13 @@ export function EditNotifierComponent({
|
||||
};
|
||||
}
|
||||
|
||||
if (type === NotifierType.WEBHOOK) {
|
||||
notifier.webhookNotifier = {
|
||||
webhookUrl: '',
|
||||
webhookMethod: WebhookMethod.POST,
|
||||
};
|
||||
}
|
||||
|
||||
setNotifier(
|
||||
JSON.parse(
|
||||
JSON.stringify({
|
||||
@@ -134,6 +148,10 @@ export function EditNotifierComponent({
|
||||
);
|
||||
}
|
||||
|
||||
if (notifier.notifierType === NotifierType.WEBHOOK) {
|
||||
return notifier.webhookNotifier?.webhookUrl;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -166,6 +184,7 @@ export function EditNotifierComponent({
|
||||
options={[
|
||||
{ label: 'Telegram', value: NotifierType.TELEGRAM },
|
||||
{ label: 'Email', value: NotifierType.EMAIL },
|
||||
{ label: 'Webhook', value: NotifierType.WEBHOOK },
|
||||
]}
|
||||
onChange={(value) => {
|
||||
setNotifierType(value);
|
||||
@@ -175,13 +194,7 @@ export function EditNotifierComponent({
|
||||
className="w-full max-w-[250px]"
|
||||
/>
|
||||
|
||||
{notifier?.notifierType === NotifierType.TELEGRAM && (
|
||||
<img src="/icons/notifiers/telegram.svg" className="ml-2 h-4 w-4" />
|
||||
)}
|
||||
|
||||
{notifier?.notifierType === NotifierType.EMAIL && (
|
||||
<img src="/icons/notifiers/email.svg" className="ml-2 h-4 w-4" />
|
||||
)}
|
||||
<img src={getNotifierLogoFromType(notifier?.notifierType)} className="ml-2 h-4 w-4" />
|
||||
</div>
|
||||
|
||||
<div className="mt-5" />
|
||||
@@ -202,6 +215,14 @@ export function EditNotifierComponent({
|
||||
setIsUnsaved={setIsUnsaved}
|
||||
/>
|
||||
)}
|
||||
|
||||
{notifier?.notifierType === NotifierType.WEBHOOK && (
|
||||
<EditWebhookNotifierComponent
|
||||
notifier={notifier}
|
||||
setNotifier={setNotifier}
|
||||
setIsUnsaved={setIsUnsaved}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-3 flex">
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
import { Input, Select, Tooltip } from 'antd';
|
||||
|
||||
import type { Notifier } from '../../../../../entity/notifiers';
|
||||
import { WebhookMethod } from '../../../../../entity/notifiers/models/WebhookMethod';
|
||||
|
||||
interface Props {
|
||||
notifier: Notifier;
|
||||
setNotifier: (notifier: Notifier) => void;
|
||||
setIsUnsaved: (isUnsaved: boolean) => void;
|
||||
}
|
||||
|
||||
export function EditWebhookNotifierComponent({ notifier, setNotifier, setIsUnsaved }: Props) {
|
||||
return (
|
||||
<>
|
||||
<div className="flex items-center">
|
||||
<div className="min-w-[110px]">Webhook URL</div>
|
||||
|
||||
<div className="w-[250px]">
|
||||
<Input
|
||||
value={notifier?.webhookNotifier?.webhookUrl || ''}
|
||||
onChange={(e) => {
|
||||
setNotifier({
|
||||
...notifier,
|
||||
webhookNotifier: {
|
||||
...(notifier.webhookNotifier || { webhookMethod: WebhookMethod.POST }),
|
||||
webhookUrl: e.target.value.trim(),
|
||||
},
|
||||
});
|
||||
setIsUnsaved(true);
|
||||
}}
|
||||
size="small"
|
||||
className="w-full"
|
||||
placeholder="https://example.com/webhook"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Tooltip
|
||||
className="cursor-pointer"
|
||||
title="The URL that will be called when a notification is triggered"
|
||||
>
|
||||
<InfoCircleOutlined className="ml-2" style={{ color: 'gray' }} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div className="mt-1 flex items-center">
|
||||
<div className="min-w-[110px]">Method</div>
|
||||
|
||||
<div className="w-[250px]">
|
||||
<Select
|
||||
value={notifier?.webhookNotifier?.webhookMethod || WebhookMethod.POST}
|
||||
onChange={(value) => {
|
||||
setNotifier({
|
||||
...notifier,
|
||||
webhookNotifier: {
|
||||
...(notifier.webhookNotifier || { webhookUrl: '' }),
|
||||
webhookMethod: value,
|
||||
},
|
||||
});
|
||||
setIsUnsaved(true);
|
||||
}}
|
||||
size="small"
|
||||
className="w-full"
|
||||
options={[
|
||||
{ value: WebhookMethod.POST, label: 'POST' },
|
||||
{ value: WebhookMethod.GET, label: 'GET' },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Tooltip
|
||||
className="cursor-pointer"
|
||||
title="The HTTP method that will be used to call the webhook"
|
||||
>
|
||||
<InfoCircleOutlined className="ml-2" style={{ color: 'gray' }} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
{notifier?.webhookNotifier?.webhookUrl && (
|
||||
<div className="mt-3">
|
||||
<div className="mb-1">Example request</div>
|
||||
|
||||
{notifier?.webhookNotifier?.webhookMethod === WebhookMethod.GET && (
|
||||
<div className="rounded bg-gray-100 p-2 px-3 text-sm break-all">
|
||||
GET {notifier?.webhookNotifier?.webhookUrl}?heading=✅ Backup completed for
|
||||
database&message=Backup completed successfully in 2m 17s.\nCompressed backup size:
|
||||
1.7GB
|
||||
</div>
|
||||
)}
|
||||
|
||||
{notifier?.webhookNotifier?.webhookMethod === WebhookMethod.POST && (
|
||||
<div className="rounded bg-gray-100 p-2 px-3 font-mono text-sm break-all whitespace-pre-line">
|
||||
{`POST ${notifier?.webhookNotifier?.webhookUrl}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"heading": "✅ Backup completed for database",
|
||||
"message": "Backup completed successfully in 2m 17s.\\nCompressed backup size: 1.7GB"
|
||||
}
|
||||
`}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { getNotifierLogoFromType } from '../../../../entity/notifiers/models/get
|
||||
import { getNotifierNameFromType } from '../../../../entity/notifiers/models/getNotifierNameFromType';
|
||||
import { ShowEmailNotifierComponent } from './notifier/ShowEmailNotifierComponent';
|
||||
import { ShowTelegramNotifierComponent } from './notifier/ShowTelegramNotifierComponent';
|
||||
import { ShowWebhookNotifierComponent } from './notifier/ShowWebhookNotifierComponent';
|
||||
|
||||
interface Props {
|
||||
notifier: Notifier;
|
||||
@@ -26,6 +27,10 @@ export function ShowNotifierComponent({ notifier }: Props) {
|
||||
{notifier?.notifierType === NotifierType.EMAIL && (
|
||||
<ShowEmailNotifierComponent notifier={notifier} />
|
||||
)}
|
||||
|
||||
{notifier?.notifierType === NotifierType.WEBHOOK && (
|
||||
<ShowWebhookNotifierComponent notifier={notifier} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import type { Notifier } from '../../../../../entity/notifiers';
|
||||
|
||||
interface Props {
|
||||
notifier: Notifier;
|
||||
}
|
||||
|
||||
export function ShowWebhookNotifierComponent({ notifier }: Props) {
|
||||
return (
|
||||
<>
|
||||
<div className="flex items-center">
|
||||
<div className="min-w-[110px]">Webhook URL</div>
|
||||
|
||||
<div className="w-[250px]">{notifier?.webhookNotifier?.webhookUrl || '-'}</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-1 mb-1 flex items-center">
|
||||
<div className="min-w-[110px]">Method</div>
|
||||
<div>{notifier?.webhookNotifier?.webhookMethod || '-'}</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user