+ {(type === "application" || type === "compose") && (
+
+ )}
{(type === "application" || type === "compose") && (
)}
@@ -252,6 +259,8 @@ export const ShowDeployments = ({
const isExpanded = expandedDescriptions.has(
deployment.deploymentId,
);
+ const canDelete =
+ deployment.status === "done" || deployment.status === "error";
return (
+ {canDelete && (
+ {
+ try {
+ await removeDeployment({
+ deploymentId: deployment.deploymentId,
+ });
+ toast.success("Deployment deleted successfully");
+ } catch (error) {
+ toast.error("Error deleting deployment");
+ }
+ }}
+ >
+
+
+ )}
+
{deployment?.rollback &&
deployment.status === "done" &&
type === "application" && (
diff --git a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx
index 7b477c92b..958eb94c7 100644
--- a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx
+++ b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx
@@ -18,6 +18,7 @@ import {
PushoverIcon,
ResendIcon,
SlackIcon,
+ TeamsIcon,
TelegramIcon,
} from "@/components/icons/notification-icons";
import { Button } from "@/components/ui/button";
@@ -164,6 +165,12 @@ export const notificationSchema = z.discriminatedUnion("type", [
webhookUrl: z.string().min(1, { message: "Webhook URL is required" }),
})
.merge(notificationBaseSchema),
+ z
+ .object({
+ type: z.literal("teams"),
+ webhookUrl: z.string().min(1, { message: "Webhook URL is required" }),
+ })
+ .merge(notificationBaseSchema),
]);
export const notificationsMap = {
@@ -183,6 +190,10 @@ export const notificationsMap = {
icon: ,
label: "Lark",
},
+ teams: {
+ icon: ,
+ label: "Microsoft Teams",
+ },
email: {
icon: ,
label: "Email",
@@ -244,6 +255,8 @@ export const HandleNotifications = ({ notificationId }: Props) => {
api.notification.testNtfyConnection.useMutation();
const { mutateAsync: testLarkConnection, isLoading: isLoadingLark } =
api.notification.testLarkConnection.useMutation();
+ const { mutateAsync: testTeamsConnection, isLoading: isLoadingTeams } =
+ api.notification.testTeamsConnection.useMutation();
const { mutateAsync: testCustomConnection, isLoading: isLoadingCustom } =
api.notification.testCustomConnection.useMutation();
@@ -278,6 +291,9 @@ export const HandleNotifications = ({ notificationId }: Props) => {
const larkMutation = notificationId
? api.notification.updateLark.useMutation()
: api.notification.createLark.useMutation();
+ const teamsMutation = notificationId
+ ? api.notification.updateTeams.useMutation()
+ : api.notification.createTeams.useMutation();
const pushoverMutation = notificationId
? api.notification.updatePushover.useMutation()
: api.notification.createPushover.useMutation();
@@ -353,7 +369,7 @@ export const HandleNotifications = ({ notificationId }: Props) => {
volumeBackup: notification.volumeBackup,
type: notification.notificationType,
webhookUrl: notification.discord?.webhookUrl,
- decoration: notification.discord?.decoration || undefined,
+ decoration: notification.discord?.decoration ?? undefined,
name: notification.name,
dockerCleanup: notification.dockerCleanup,
serverThreshold: notification.serverThreshold,
@@ -400,7 +416,7 @@ export const HandleNotifications = ({ notificationId }: Props) => {
volumeBackup: notification.volumeBackup,
type: notification.notificationType,
appToken: notification.gotify?.appToken,
- decoration: notification.gotify?.decoration || undefined,
+ decoration: notification.gotify?.decoration ?? undefined,
priority: notification.gotify?.priority,
serverUrl: notification.gotify?.serverUrl,
name: notification.name,
@@ -435,6 +451,19 @@ export const HandleNotifications = ({ notificationId }: Props) => {
volumeBackup: notification.volumeBackup,
serverThreshold: notification.serverThreshold,
});
+ } else if (notification.notificationType === "teams") {
+ form.reset({
+ appBuildError: notification.appBuildError,
+ appDeploy: notification.appDeploy,
+ dokployRestart: notification.dokployRestart,
+ databaseBackup: notification.databaseBackup,
+ volumeBackup: notification.volumeBackup,
+ type: notification.notificationType,
+ webhookUrl: notification.teams?.webhookUrl,
+ name: notification.name,
+ dockerCleanup: notification.dockerCleanup,
+ serverThreshold: notification.serverThreshold,
+ });
} else if (notification.notificationType === "custom") {
form.reset({
appBuildError: notification.appBuildError,
@@ -488,6 +517,7 @@ export const HandleNotifications = ({ notificationId }: Props) => {
gotify: gotifyMutation,
ntfy: ntfyMutation,
lark: larkMutation,
+ teams: teamsMutation,
custom: customMutation,
pushover: pushoverMutation,
};
@@ -630,6 +660,20 @@ export const HandleNotifications = ({ notificationId }: Props) => {
larkId: notification?.larkId || "",
serverThreshold: serverThreshold,
});
+ } else if (data.type === "teams") {
+ promise = teamsMutation.mutateAsync({
+ appBuildError: appBuildError,
+ appDeploy: appDeploy,
+ dokployRestart: dokployRestart,
+ databaseBackup: databaseBackup,
+ volumeBackup: volumeBackup,
+ webhookUrl: data.webhookUrl,
+ name: data.name,
+ dockerCleanup: dockerCleanup,
+ notificationId: notificationId || "",
+ teamsId: notification?.teamsId || "",
+ serverThreshold: serverThreshold,
+ });
} else if (data.type === "custom") {
// Convert headers array to object
const headersRecord =
@@ -1465,6 +1509,32 @@ export const HandleNotifications = ({ notificationId }: Props) => {
/>
>
)}
+
+ {type === "teams" && (
+ <>
+ (
+
+ Webhook URL
+
+
+
+
+ Incoming Webhook URL from a Teams channel. Add an
+ Incoming Webhook in your channel settings to get the
+ URL.
+
+
+
+ )}
+ />
+ >
+ )}
{type === "pushover" && (
<>
{
isLoadingGotify ||
isLoadingNtfy ||
isLoadingLark ||
+ isLoadingTeams ||
isLoadingCustom ||
isLoadingPushover
}
@@ -1841,6 +1912,10 @@ export const HandleNotifications = ({ notificationId }: Props) => {
await testLarkConnection({
webhookUrl: data.webhookUrl,
});
+ } else if (data.type === "teams") {
+ await testTeamsConnection({
+ webhookUrl: data.webhookUrl,
+ });
} else if (data.type === "custom") {
const headersRecord =
data.headers && data.headers.length > 0
diff --git a/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx b/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx
index a3c1377ae..60124cc6a 100644
--- a/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx
+++ b/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx
@@ -7,6 +7,7 @@ import {
NtfyIcon,
ResendIcon,
SlackIcon,
+ TeamsIcon,
TelegramIcon,
} from "@/components/icons/notification-icons";
import { DialogAction } from "@/components/shared/dialog-action";
@@ -37,7 +38,7 @@ export const ShowNotifications = () => {
Add your providers to receive notifications, like Discord, Slack,
- Telegram, Email, Resend, Lark.
+ Telegram, Teams, Email, Resend, Lark.
@@ -112,6 +113,11 @@ export const ShowNotifications = () => {
)}
+ {notification.notificationType === "teams" && (
+
+
+
+ )}
{notification.name}
diff --git a/apps/dokploy/components/dashboard/settings/profile/profile-form.tsx b/apps/dokploy/components/dashboard/settings/profile/profile-form.tsx
index 461a4c17c..8540835c8 100644
--- a/apps/dokploy/components/dashboard/settings/profile/profile-form.tsx
+++ b/apps/dokploy/components/dashboard/settings/profile/profile-form.tsx
@@ -1,6 +1,5 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { Loader2, Palette, User } from "lucide-react";
-import { useTranslation } from "next-i18next";
import { useEffect, useMemo, useRef, useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -73,7 +72,6 @@ export const ProfileForm = () => {
isError,
error,
} = api.user.update.useMutation();
- const { t } = useTranslation("settings");
const [gravatarHash, setGravatarHash] = useState
(null);
const colorInputRef = useRef(null);
@@ -157,10 +155,10 @@ export const ProfileForm = () => {
- {t("settings.profile.title")}
+ Account
- {t("settings.profile.description")}
+ Change the details of your profile here.
@@ -213,12 +211,9 @@ export const ProfileForm = () => {
name="email"
render={({ field }) => (
- {t("settings.profile.email")}
+ Email
-
+
@@ -233,7 +228,7 @@ export const ProfileForm = () => {
@@ -247,13 +242,11 @@ export const ProfileForm = () => {
name="password"
render={({ field }) => (
-
- {t("settings.profile.password")}
-
+ Password
@@ -268,9 +261,7 @@ export const ProfileForm = () => {
name="image"
render={({ field }) => (
-
- {t("settings.profile.avatar")}
-
+ Avatar
{
@@ -454,7 +445,7 @@ export const ProfileForm = () => {
diff --git a/apps/dokploy/components/dashboard/settings/servers/actions/show-dokploy-actions.tsx b/apps/dokploy/components/dashboard/settings/servers/actions/show-dokploy-actions.tsx
index 42b73cf59..b4a9ff946 100644
--- a/apps/dokploy/components/dashboard/settings/servers/actions/show-dokploy-actions.tsx
+++ b/apps/dokploy/components/dashboard/settings/servers/actions/show-dokploy-actions.tsx
@@ -1,4 +1,3 @@
-import { useTranslation } from "next-i18next";
import { toast } from "sonner";
import { UpdateServerIp } from "@/components/dashboard/settings/web-server/update-server-ip";
import { Button } from "@/components/ui/button";
@@ -17,7 +16,6 @@ import { TerminalModal } from "../../web-server/terminal-modal";
import { GPUSupportModal } from "../gpu-support-modal";
export const ShowDokployActions = () => {
- const { t } = useTranslation("settings");
const { mutateAsync: reloadServer, isLoading } =
api.settings.reloadServer.useMutation();
@@ -30,13 +28,11 @@ export const ShowDokployActions = () => {
-
- {t("settings.server.webServer.actions")}
-
+ Actions
{
}}
className="cursor-pointer"
>
- {t("settings.server.webServer.reload")}
+ Reload
- {t("settings.common.enterTerminal")}
+ Terminal
e.preventDefault()}
>
- {t("settings.server.webServer.watchLogs")}
+ View Logs
@@ -70,7 +66,7 @@ export const ShowDokployActions = () => {
className="cursor-pointer"
onSelect={(e) => e.preventDefault()}
>
- {t("settings.server.webServer.updateServerIp")}
+ Update Server IP
diff --git a/apps/dokploy/components/dashboard/settings/servers/actions/show-storage-actions.tsx b/apps/dokploy/components/dashboard/settings/servers/actions/show-storage-actions.tsx
index 5bf3b8fc6..750b27f22 100644
--- a/apps/dokploy/components/dashboard/settings/servers/actions/show-storage-actions.tsx
+++ b/apps/dokploy/components/dashboard/settings/servers/actions/show-storage-actions.tsx
@@ -1,4 +1,3 @@
-import { useTranslation } from "next-i18next";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import {
@@ -16,7 +15,6 @@ interface Props {
serverId?: string;
}
export const ShowStorageActions = ({ serverId }: Props) => {
- const { t } = useTranslation("settings");
const { mutateAsync: cleanAll, isLoading: cleanAllIsLoading } =
api.settings.cleanAll.useMutation();
@@ -69,13 +67,11 @@ export const ShowStorageActions = ({ serverId }: Props) => {
}
variant="outline"
>
- {t("settings.server.webServer.storage.label")}
+ Space
-
- {t("settings.server.webServer.actions")}
-
+ Actions
{
});
}}
>
-
- {t("settings.server.webServer.storage.cleanUnusedImages")}
-
+ Clean unused images
{
});
}}
>
-
- {t("settings.server.webServer.storage.cleanUnusedVolumes")}
-
+ Clean unused volumes
{
});
}}
>
-
- {t("settings.server.webServer.storage.cleanStoppedContainers")}
-
+ Clean stopped containers
{
});
}}
>
-
- {t("settings.server.webServer.storage.cleanDockerBuilder")}
-
+ Clean Docker Builder & System
{!serverId && (
{
});
}}
>
-
- {t("settings.server.webServer.storage.cleanMonitoring")}
-
+ Clean Monitoring
)}
@@ -202,7 +188,7 @@ export const ShowStorageActions = ({ serverId }: Props) => {
});
}}
>
- {t("settings.server.webServer.storage.cleanAll")}
+ Clean all
diff --git a/apps/dokploy/components/dashboard/settings/servers/actions/show-traefik-actions.tsx b/apps/dokploy/components/dashboard/settings/servers/actions/show-traefik-actions.tsx
index 5b4d751ff..11c3c19c8 100644
--- a/apps/dokploy/components/dashboard/settings/servers/actions/show-traefik-actions.tsx
+++ b/apps/dokploy/components/dashboard/settings/servers/actions/show-traefik-actions.tsx
@@ -1,4 +1,3 @@
-import { useTranslation } from "next-i18next";
import { toast } from "sonner";
import { AlertBlock } from "@/components/shared/alert-block";
import { DialogAction } from "@/components/shared/dialog-action";
@@ -22,7 +21,6 @@ interface Props {
serverId?: string;
}
export const ShowTraefikActions = ({ serverId }: Props) => {
- const { t } = useTranslation("settings");
const { mutateAsync: reloadTraefik, isLoading: reloadTraefikIsLoading } =
api.settings.reloadTraefik.useMutation();
@@ -75,13 +73,11 @@ export const ShowTraefikActions = ({ serverId }: Props) => {
}
variant="outline"
>
- {t("settings.server.webServer.traefik.label")}
+ Traefik
-
- {t("settings.server.webServer.actions")}
-
+ Actions
{
className="cursor-pointer"
disabled={isReloadHealthCheckExecuting}
>
- {t("settings.server.webServer.reload")}
+ Reload
{
onSelect={(e) => e.preventDefault()}
className="cursor-pointer"
>
- {t("settings.server.webServer.watchLogs")}
+ View Logs
@@ -119,7 +115,7 @@ export const ShowTraefikActions = ({ serverId }: Props) => {
onSelect={(e) => e.preventDefault()}
className="cursor-pointer"
>
- {t("settings.server.webServer.traefik.modifyEnv")}
+ Modify Environment
@@ -176,7 +172,7 @@ export const ShowTraefikActions = ({ serverId }: Props) => {
onSelect={(e) => e.preventDefault()}
className="cursor-pointer"
>
- {t("settings.server.webServer.traefik.managePorts")}
+ Additional Port Mappings
diff --git a/apps/dokploy/components/dashboard/settings/servers/handle-servers.tsx b/apps/dokploy/components/dashboard/settings/servers/handle-servers.tsx
index 99804ba6b..010f0d2f4 100644
--- a/apps/dokploy/components/dashboard/settings/servers/handle-servers.tsx
+++ b/apps/dokploy/components/dashboard/settings/servers/handle-servers.tsx
@@ -1,7 +1,6 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { Pencil, PlusIcon } from "lucide-react";
import Link from "next/link";
-import { useTranslation } from "next-i18next";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -63,8 +62,6 @@ interface Props {
}
export const HandleServers = ({ serverId, asButton = false }: Props) => {
- const { t } = useTranslation("settings");
-
const utils = api.useUtils();
const [isOpen, setIsOpen] = useState(false);
const { data: canCreateMoreServers, refetch } =
@@ -365,7 +362,7 @@ export const HandleServers = ({ serverId, asButton = false }: Props) => {
name="ipAddress"
render={({ field }) => (
- {t("settings.terminal.ipAddress")}
+ IP Address
@@ -379,7 +376,7 @@ export const HandleServers = ({ serverId, asButton = false }: Props) => {
name="port"
render={({ field }) => (
- {t("settings.terminal.port")}
+ Port
{
name="username"
render={({ field }) => (
- {t("settings.terminal.username")}
+ Username
diff --git a/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx b/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx
index 92d6fc5c3..657ac2453 100644
--- a/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx
+++ b/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx
@@ -13,7 +13,6 @@ import {
} from "lucide-react";
import Link from "next/link";
import { useRouter } from "next/router";
-import { useTranslation } from "next-i18next";
import { toast } from "sonner";
import { AlertBlock } from "@/components/shared/alert-block";
import { DialogAction } from "@/components/shared/dialog-action";
@@ -52,7 +51,6 @@ import { ShowTraefikFileSystemModal } from "./show-traefik-file-system-modal";
import { WelcomeSuscription } from "./welcome-stripe/welcome-suscription";
export const ShowServers = () => {
- const { t } = useTranslation("settings");
const router = useRouter();
const query = router.query;
const { data, refetch, isLoading } = api.server.all.useQuery();
diff --git a/apps/dokploy/components/dashboard/settings/web-domain.tsx b/apps/dokploy/components/dashboard/settings/web-domain.tsx
index e0be5c7f3..f593d2b10 100644
--- a/apps/dokploy/components/dashboard/settings/web-domain.tsx
+++ b/apps/dokploy/components/dashboard/settings/web-domain.tsx
@@ -1,6 +1,5 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { GlobeIcon } from "lucide-react";
-import { useTranslation } from "next-i18next";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -66,7 +65,6 @@ const addServerDomain = z
type AddServerDomain = z.infer;
export const WebDomain = () => {
- const { t } = useTranslation("settings");
const { data, refetch } = api.settings.getWebServerSettings.useQuery();
const { mutateAsync, isLoading } =
api.settings.assignDomainServer.useMutation();
@@ -119,10 +117,10 @@ export const WebDomain = () => {
- {t("settings.server.domain.title")}
+ Server Domain
- {t("settings.server.domain.description")}
+ Add a domain to your server application.
@@ -151,9 +149,7 @@ export const WebDomain = () => {
render={({ field }) => {
return (
-
- {t("settings.server.domain.form.domain")}
-
+ Domain
{
render={({ field }) => {
return (
-
- {t("settings.server.domain.form.letsEncryptEmail")}
-
+ Let's Encrypt Email
{
render={({ field }) => {
return (
-
- {t("settings.server.domain.form.certificate.label")}
-
+ Certificate Provider
@@ -254,7 +236,7 @@ export const WebDomain = () => {
diff --git a/apps/dokploy/components/dashboard/settings/web-server.tsx b/apps/dokploy/components/dashboard/settings/web-server.tsx
index c9cb7985b..d9df975e7 100644
--- a/apps/dokploy/components/dashboard/settings/web-server.tsx
+++ b/apps/dokploy/components/dashboard/settings/web-server.tsx
@@ -1,5 +1,4 @@
import { ServerIcon } from "lucide-react";
-import { useTranslation } from "next-i18next";
import {
Card,
CardContent,
@@ -15,7 +14,6 @@ import { ToggleDockerCleanup } from "./servers/actions/toggle-docker-cleanup";
import { UpdateServer } from "./web-server/update-server";
export const WebServer = () => {
- const { t } = useTranslation("settings");
const { data: webServerSettings } =
api.settings.getWebServerSettings.useQuery();
@@ -29,18 +27,16 @@ export const WebServer = () => {
- {t("settings.server.webServer.title")}
+ Web Server
-
- {t("settings.server.webServer.description")}
-
+ Reload or clean the web server.
{/*
- {t("settings.server.webServer.title")}
+ Web Server
- {t("settings.server.webServer.description")}
+ Reload or clean the web server.
*/}
diff --git a/apps/dokploy/components/dashboard/settings/web-server/local-server-config.tsx b/apps/dokploy/components/dashboard/settings/web-server/local-server-config.tsx
index cb0218c5a..3ea1d965c 100644
--- a/apps/dokploy/components/dashboard/settings/web-server/local-server-config.tsx
+++ b/apps/dokploy/components/dashboard/settings/web-server/local-server-config.tsx
@@ -1,6 +1,5 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { Settings } from "lucide-react";
-import { useTranslation } from "next-i18next";
import { useForm } from "react-hook-form";
import { z } from "zod";
import {
@@ -52,8 +51,6 @@ interface Props {
}
const LocalServerConfig = ({ onSave }: Props) => {
- const { t } = useTranslation("settings");
-
const form = useForm({
defaultValues: getLocalServerData(),
resolver: zodResolver(Schema),
@@ -77,9 +74,7 @@ const LocalServerConfig = ({ onSave }: Props) => {
-
- {t("settings.terminal.connectionSettings")}
-
+ Connection settings
@@ -96,7 +91,7 @@ const LocalServerConfig = ({ onSave }: Props) => {
name="port"
render={({ field }) => (
- {t("settings.terminal.port")}
+ Port
{
name="username"
render={({ field }) => (
- {t("settings.terminal.username")}
+ Username
@@ -142,7 +137,7 @@ const LocalServerConfig = ({ onSave }: Props) => {
className="ml-auto"
disabled={!form.formState.isDirty}
>
- {t("settings.common.save")}
+ Save
diff --git a/apps/dokploy/components/dashboard/settings/web-server/manage-traefik-ports.tsx b/apps/dokploy/components/dashboard/settings/web-server/manage-traefik-ports.tsx
index 73973ef06..9d29c1937 100644
--- a/apps/dokploy/components/dashboard/settings/web-server/manage-traefik-ports.tsx
+++ b/apps/dokploy/components/dashboard/settings/web-server/manage-traefik-ports.tsx
@@ -1,6 +1,5 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { ArrowRightLeft, Plus, Trash2 } from "lucide-react";
-import { useTranslation } from "next-i18next";
import { useHealthCheckAfterMutation } from "@/hooks/use-health-check-after-mutation";
import type React from "react";
import { useEffect, useState } from "react";
@@ -56,7 +55,6 @@ const TraefikPortsSchema = z.object({
type TraefikPortsForm = z.infer;
export const ManageTraefikPorts = ({ children, serverId }: Props) => {
- const { t } = useTranslation("settings");
const [open, setOpen] = useState(false);
const form = useForm({
@@ -84,7 +82,7 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => {
isExecuting: isHealthCheckExecuting,
} = useHealthCheckAfterMutation({
initialDelay: 5000,
- successMessage: t("settings.server.webServer.traefik.portsUpdated"),
+ successMessage: "Ports updated successfully",
onSuccess: () => {
refetchPorts();
setOpen(false);
@@ -129,14 +127,12 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => {
- {t("settings.server.webServer.traefik.managePorts")}
+ Additional Port Mappings
- {t(
- "settings.server.webServer.traefik.managePortsDescription",
- )}
+ Add or remove additional ports for Traefik
{fields.length} port mapping{fields.length !== 1 ? "s" : ""}{" "}
configured
@@ -179,9 +175,7 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => {
render={({ field }) => (
- {t(
- "settings.server.webServer.traefik.targetPort",
- )}
+ Target Port
{
render={({ field }) => (
- {t(
- "settings.server.webServer.traefik.publishedPort",
- )}
+ Published Port
- {dokployVersion} | {releaseTag}
+ {dokployVersion}{" "}
+ {(releaseTag === "canary" || releaseTag === "feature") &&
+ `(${releaseTag})`}
)}
diff --git a/apps/dokploy/components/icons/notification-icons.tsx b/apps/dokploy/components/icons/notification-icons.tsx
index 05f66146a..f902af415 100644
--- a/apps/dokploy/components/icons/notification-icons.tsx
+++ b/apps/dokploy/components/icons/notification-icons.tsx
@@ -88,6 +88,35 @@ export const DiscordIcon = ({ className }: Props) => {
);
};
+export const TeamsIcon = ({ className }: Props) => {
+ return (
+
+ );
+};
+
export const LarkIcon = ({ className }: Props) => {
return (