mirror of
https://github.com/crocofied/CoreControl.git
synced 2025-12-29 16:14:43 +00:00
i18n final
This commit is contained in:
@@ -36,6 +36,7 @@ import {
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { Checkbox } from "@/components/ui/checkbox"
|
||||
import { Textarea } from "@/components/ui/textarea"
|
||||
import { useTranslations } from "next-intl"
|
||||
|
||||
interface NotificationsResponse {
|
||||
notifications: any[]
|
||||
@@ -46,6 +47,7 @@ interface NotificationResponse {
|
||||
}
|
||||
|
||||
export default function Settings() {
|
||||
const t = useTranslations()
|
||||
const { theme, setTheme } = useTheme()
|
||||
|
||||
const [email, setEmail] = useState<string>("")
|
||||
@@ -92,7 +94,7 @@ export default function Settings() {
|
||||
setEmailError("")
|
||||
|
||||
if (!email) {
|
||||
setEmailError("Email is required")
|
||||
setEmailError(t('Settings.UserSettings.ChangeEmail.EmailRequired'))
|
||||
setEmailErrorVisible(true)
|
||||
setTimeout(() => {
|
||||
setEmailErrorVisible(false)
|
||||
@@ -123,7 +125,7 @@ export default function Settings() {
|
||||
const changePassword = async () => {
|
||||
try {
|
||||
if (password !== confirmPassword) {
|
||||
setPasswordError("Passwords do not match")
|
||||
setPasswordError(t('Settings.UserSettings.ChangePassword.PasswordsDontMatch'))
|
||||
setPasswordErrorVisible(true)
|
||||
setTimeout(() => {
|
||||
setPasswordErrorVisible(false)
|
||||
@@ -132,7 +134,7 @@ export default function Settings() {
|
||||
return
|
||||
}
|
||||
if (!oldPassword || !password || !confirmPassword) {
|
||||
setPasswordError("All fields are required")
|
||||
setPasswordError(t('Settings.UserSettings.ChangePassword.AllFieldsRequired'))
|
||||
setPasswordErrorVisible(true)
|
||||
setTimeout(() => {
|
||||
setPasswordErrorVisible(false)
|
||||
@@ -263,7 +265,7 @@ export default function Settings() {
|
||||
const response = await axios.post("/api/notifications/test", {
|
||||
notificationId: id,
|
||||
})
|
||||
toast.success("Notification will be sent in a few seconds.")
|
||||
toast.success(t('Settings.Notifications.TestSuccess'))
|
||||
} catch (error: any) {
|
||||
toast.error(error.response.data.error)
|
||||
}
|
||||
@@ -280,15 +282,11 @@ export default function Settings() {
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem className="hidden md:block">
|
||||
<BreadcrumbPage>/</BreadcrumbPage>
|
||||
<BreadcrumbPage>{t('Settings.Breadcrumb.Dashboard')}</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator className="hidden md:block" />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Dashboard</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator className="hidden md:block" />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Settings</BreadcrumbPage>
|
||||
<BreadcrumbPage>{t('Settings.Breadcrumb.Settings')}</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
@@ -296,31 +294,31 @@ export default function Settings() {
|
||||
</header>
|
||||
<div className="p-6">
|
||||
<div className="pb-4">
|
||||
<span className="text-3xl font-bold">Settings</span>
|
||||
<span className="text-3xl font-bold">{t('Settings.Title')}</span>
|
||||
</div>
|
||||
<div className="grid gap-6">
|
||||
<Card className="overflow-hidden border-2 border-muted/20 shadow-sm">
|
||||
<CardHeader className="bg-muted/10 px-6 py-4 border-b">
|
||||
<div className="flex items-center gap-2">
|
||||
<User className="h-5 w-5 text-primary" />
|
||||
<h2 className="text-xl font-semibold">User Settings</h2>
|
||||
<h2 className="text-xl font-semibold">{t('Settings.UserSettings.Title')}</h2>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="pb-6">
|
||||
<div className="text-sm text-muted-foreground mb-6">
|
||||
Manage your user settings here. You can change your email, password, and other account settings.
|
||||
{t('Settings.UserSettings.Description')}
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
<div className="space-y-4">
|
||||
<div className="border-b pb-2">
|
||||
<h3 className="font-semibold text-lg">Change Email</h3>
|
||||
<h3 className="font-semibold text-lg">{t('Settings.UserSettings.ChangeEmail.Title')}</h3>
|
||||
</div>
|
||||
|
||||
{emailErrorVisible && (
|
||||
<Alert variant="destructive" className="animate-in fade-in-50">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertTitle>Error</AlertTitle>
|
||||
<AlertTitle>{t('Common.Error')}</AlertTitle>
|
||||
<AlertDescription>{emailError}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
@@ -328,34 +326,33 @@ export default function Settings() {
|
||||
{emailSuccess && (
|
||||
<Alert className="border-green-200 bg-green-50 text-green-800 dark:border-green-800 dark:bg-green-950 dark:text-green-300 animate-in fade-in-50">
|
||||
<Check className="h-4 w-4" />
|
||||
<AlertTitle>Success</AlertTitle>
|
||||
<AlertDescription>Email changed successfully.</AlertDescription>
|
||||
<AlertTitle>{t('Settings.UserSettings.ChangeEmail.Success')}</AlertTitle>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<div className="space-y-3">
|
||||
<Input
|
||||
type="email"
|
||||
placeholder="Enter new email"
|
||||
placeholder={t('Settings.UserSettings.ChangeEmail.Placeholder')}
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
className="h-11"
|
||||
/>
|
||||
<Button onClick={changeEmail} className="w-full h-11">
|
||||
Change Email
|
||||
{t('Settings.UserSettings.ChangeEmail.Button')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="border-b pb-2">
|
||||
<h3 className="font-semibold text-lg">Change Password</h3>
|
||||
<h3 className="font-semibold text-lg">{t('Settings.UserSettings.ChangePassword.Title')}</h3>
|
||||
</div>
|
||||
|
||||
{passwordErrorVisible && (
|
||||
<Alert variant="destructive" className="animate-in fade-in-50">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertTitle>Error</AlertTitle>
|
||||
<AlertTitle>{t('Common.Error')}</AlertTitle>
|
||||
<AlertDescription>{passwordError}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
@@ -363,35 +360,34 @@ export default function Settings() {
|
||||
{passwordSuccess && (
|
||||
<Alert className="border-green-200 bg-green-50 text-green-800 dark:border-green-800 dark:bg-green-950 dark:text-green-300 animate-in fade-in-50">
|
||||
<Check className="h-4 w-4" />
|
||||
<AlertTitle>Success</AlertTitle>
|
||||
<AlertDescription>Password changed successfully.</AlertDescription>
|
||||
<AlertTitle>{t('Settings.UserSettings.ChangePassword.Success')}</AlertTitle>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<div className="space-y-3">
|
||||
<Input
|
||||
type="password"
|
||||
placeholder="Enter old password"
|
||||
placeholder={t('Settings.UserSettings.ChangePassword.OldPassword')}
|
||||
value={oldPassword}
|
||||
onChange={(e) => setOldPassword(e.target.value)}
|
||||
className="h-11"
|
||||
/>
|
||||
<Input
|
||||
type="password"
|
||||
placeholder="Enter new password"
|
||||
placeholder={t('Settings.UserSettings.ChangePassword.NewPassword')}
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
className="h-11"
|
||||
/>
|
||||
<Input
|
||||
type="password"
|
||||
placeholder="Confirm new password"
|
||||
placeholder={t('Settings.UserSettings.ChangePassword.ConfirmPassword')}
|
||||
value={confirmPassword}
|
||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||
className="h-11"
|
||||
/>
|
||||
<Button onClick={changePassword} className="w-full h-11">
|
||||
Change Password
|
||||
{t('Settings.UserSettings.ChangePassword.Button')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -403,25 +399,25 @@ export default function Settings() {
|
||||
<CardHeader className="bg-muted/10 px-6 py-4 border-b">
|
||||
<div className="flex items-center gap-2">
|
||||
<Palette className="h-5 w-5 text-primary" />
|
||||
<h2 className="text-xl font-semibold">Theme Settings</h2>
|
||||
<h2 className="text-xl font-semibold">{t('Settings.ThemeSettings.Title')}</h2>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="pb-6">
|
||||
<div className="text-sm text-muted-foreground mb-6">
|
||||
Select a theme for the application. You can choose between light, dark, or system theme.
|
||||
{t('Settings.ThemeSettings.Description')}
|
||||
</div>
|
||||
|
||||
<div className="max-w-md">
|
||||
<Select value={theme} onValueChange={(value: string) => setTheme(value)}>
|
||||
<SelectTrigger className="w-full h-11">
|
||||
<SelectValue>
|
||||
{(theme ?? "system").charAt(0).toUpperCase() + (theme ?? "system").slice(1)}
|
||||
{t(`Settings.ThemeSettings.${(theme ?? "system").charAt(0).toUpperCase() + (theme ?? "system").slice(1)}`)}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="light">Light</SelectItem>
|
||||
<SelectItem value="dark">Dark</SelectItem>
|
||||
<SelectItem value="system">System</SelectItem>
|
||||
<SelectItem value="light">{t('Settings.ThemeSettings.Light')}</SelectItem>
|
||||
<SelectItem value="dark">{t('Settings.ThemeSettings.Dark')}</SelectItem>
|
||||
<SelectItem value="system">{t('Settings.ThemeSettings.System')}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
@@ -434,61 +430,59 @@ export default function Settings() {
|
||||
<div className="bg-muted/20 p-2 rounded-full">
|
||||
<Bell className="h-5 w-5 text-primary" />
|
||||
</div>
|
||||
<h2 className="text-xl font-semibold">Notifications</h2>
|
||||
<h2 className="text-xl font-semibold">{t('Settings.Notifications.Title')}</h2>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-6">
|
||||
<div className="text-sm text-muted-foreground mb-6">
|
||||
Set up notifications to get instantly alerted when an application changes status.
|
||||
{t('Settings.Notifications.Description')}
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button className="w-full h-11 flex items-center gap-2">
|
||||
Add Notification Channel
|
||||
{t('Settings.Notifications.AddChannel')}
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogTitle>Add Notification</AlertDialogTitle>
|
||||
<AlertDialogTitle>{t('Settings.Notifications.AddNotification.Title')}</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
<div className="space-y-4">
|
||||
<Input
|
||||
type="text"
|
||||
id="notificationName"
|
||||
placeholder="Notification Name (optional)"
|
||||
placeholder={t('Settings.Notifications.AddNotification.Name')}
|
||||
onChange={(e) => setNotificationName(e.target.value)}
|
||||
/>
|
||||
<Select value={notificationType} onValueChange={(value: string) => setNotificationType(value)}>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Notification Type" />
|
||||
<SelectValue placeholder={t('Settings.Notifications.AddNotification.Type')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="smtp">SMTP</SelectItem>
|
||||
<SelectItem value="telegram">Telegram</SelectItem>
|
||||
<SelectItem value="discord">Discord</SelectItem>
|
||||
<SelectItem value="gotify">Gotify</SelectItem>
|
||||
<SelectItem value="ntfy">Ntfy</SelectItem>
|
||||
<SelectItem value="pushover">Pushover</SelectItem>
|
||||
<SelectItem value="smtp">{t('Settings.Notifications.AddNotification.SMTP.Title')}</SelectItem>
|
||||
<SelectItem value="telegram">{t('Settings.Notifications.AddNotification.Telegram.Title')}</SelectItem>
|
||||
<SelectItem value="discord">{t('Settings.Notifications.AddNotification.Discord.Title')}</SelectItem>
|
||||
<SelectItem value="gotify">{t('Settings.Notifications.AddNotification.Gotify.Title')}</SelectItem>
|
||||
<SelectItem value="ntfy">{t('Settings.Notifications.AddNotification.Ntfy.Title')}</SelectItem>
|
||||
<SelectItem value="pushover">{t('Settings.Notifications.AddNotification.Pushover.Title')}</SelectItem>
|
||||
</SelectContent>
|
||||
|
||||
{notificationType === "smtp" && (
|
||||
<div className="mt-4 space-y-4">
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div className="space-y-1.5">
|
||||
<Label htmlFor="smtpHost">SMTP Host</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.SMTP.Host')}</Label>
|
||||
<Input
|
||||
type="text"
|
||||
id="smtpHost"
|
||||
placeholder="smtp.example.com"
|
||||
onChange={(e) => setSmtpHost(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label htmlFor="smtpPort">SMTP Port</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.SMTP.Port')}</Label>
|
||||
<Input
|
||||
type="number"
|
||||
id="smtpPort"
|
||||
placeholder="587"
|
||||
onChange={(e) => setSmtpPort(Number(e.target.value))}
|
||||
/>
|
||||
@@ -498,26 +492,24 @@ export default function Settings() {
|
||||
<div className="flex items-center space-x-2 pt-2 pb-4">
|
||||
<Checkbox id="smtpSecure" onCheckedChange={(checked: any) => setSmtpSecure(checked)} />
|
||||
<Label htmlFor="smtpSecure" className="text-sm font-medium leading-none">
|
||||
Secure Connection (TLS/SSL)
|
||||
{t('Settings.Notifications.AddNotification.SMTP.Secure')}
|
||||
</Label>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4">
|
||||
<div className="space-y-1.5">
|
||||
<Label htmlFor="smtpUser">SMTP Username</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.SMTP.User')}</Label>
|
||||
<Input
|
||||
type="text"
|
||||
id="smtpUser"
|
||||
placeholder="user@example.com"
|
||||
onChange={(e) => setSmtpUsername(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<Label htmlFor="smtpPass">SMTP Password</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.SMTP.Pass')}</Label>
|
||||
<Input
|
||||
type="password"
|
||||
id="smtpPass"
|
||||
placeholder="••••••••"
|
||||
onChange={(e) => setSmtpPassword(e.target.value)}
|
||||
/>
|
||||
@@ -525,20 +517,18 @@ export default function Settings() {
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div className="space-y-1.5">
|
||||
<Label htmlFor="smtpFrom">From Address</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.SMTP.From')}</Label>
|
||||
<Input
|
||||
type="email"
|
||||
id="smtpFrom"
|
||||
placeholder="noreply@example.com"
|
||||
onChange={(e) => setSmtpFrom(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<Label htmlFor="smtpTo">To Address</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.SMTP.To')}</Label>
|
||||
<Input
|
||||
type="email"
|
||||
id="smtpTo"
|
||||
placeholder="admin@example.com"
|
||||
onChange={(e) => setSmtpTo(e.target.value)}
|
||||
/>
|
||||
@@ -551,20 +541,16 @@ export default function Settings() {
|
||||
{notificationType === "telegram" && (
|
||||
<div className="mt-4 space-y-2">
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="telegramToken">Bot Token</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.Telegram.Token')}</Label>
|
||||
<Input
|
||||
type="text"
|
||||
id="telegramToken"
|
||||
placeholder=""
|
||||
onChange={(e) => setTelegramToken(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="telegramChatId">Chat ID</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.Telegram.ChatId')}</Label>
|
||||
<Input
|
||||
type="text"
|
||||
id="telegramChatId"
|
||||
placeholder=""
|
||||
onChange={(e) => setTelegramChatId(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
@@ -574,11 +560,9 @@ export default function Settings() {
|
||||
{notificationType === "discord" && (
|
||||
<div className="mt-4">
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="discordWebhook">Webhook URL</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.Discord.Webhook')}</Label>
|
||||
<Input
|
||||
type="text"
|
||||
id="discordWebhook"
|
||||
placeholder=""
|
||||
onChange={(e) => setDiscordWebhook(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
@@ -588,19 +572,15 @@ export default function Settings() {
|
||||
{notificationType === "gotify" && (
|
||||
<div className="mt-4">
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="gotifyUrl">Gotify URL</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.Gotify.Url')}</Label>
|
||||
<Input
|
||||
type="text"
|
||||
id="gotifyUrl"
|
||||
placeholder=""
|
||||
onChange={(e) => setGotifyUrl(e.target.value)}
|
||||
/>
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="gotifyToken">Gotify Token</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.Gotify.Token')}</Label>
|
||||
<Input
|
||||
type="text"
|
||||
id="gotifyToken"
|
||||
placeholder=""
|
||||
onChange={(e) => setGotifyToken(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
@@ -611,19 +591,15 @@ export default function Settings() {
|
||||
{notificationType === "ntfy" && (
|
||||
<div className="mt-4">
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="ntfyUrl">Ntfy URL</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.Ntfy.Url')}</Label>
|
||||
<Input
|
||||
type="text"
|
||||
id="ntfyUrl"
|
||||
placeholder=""
|
||||
onChange={(e) => setNtfyUrl(e.target.value)}
|
||||
/>
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="ntfyToken">Ntfy Token</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.Ntfy.Token')}</Label>
|
||||
<Input
|
||||
type="text"
|
||||
id="ntfyToken"
|
||||
placeholder=""
|
||||
onChange={(e) => setNtfyToken(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
@@ -634,31 +610,28 @@ export default function Settings() {
|
||||
{notificationType === "pushover" && (
|
||||
<div className="mt-4 flex flex-col gap-2">
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="pushoverUrl">Pushover URL</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.Pushover.Url')}</Label>
|
||||
<Input
|
||||
type="text"
|
||||
id="pushoverUrl"
|
||||
placeholder="e.g. https://api.pushover.net/1/messages.json"
|
||||
placeholder={t('Settings.Notifications.AddNotification.Pushover.UrlPlaceholder')}
|
||||
onChange={(e) => setPushoverUrl(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="pushoverToken">Pushover Token</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.Pushover.Token')}</Label>
|
||||
<Input
|
||||
type="text"
|
||||
id="pushoverToken"
|
||||
placeholder="e.g. 1234567890"
|
||||
placeholder={t('Settings.Notifications.AddNotification.Pushover.TokenPlaceholder')}
|
||||
onChange={(e) => setPushoverToken(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="pushoverUser">Pushover User</Label>
|
||||
<Label>{t('Settings.Notifications.AddNotification.Pushover.User')}</Label>
|
||||
<Input
|
||||
type="text"
|
||||
id="pushoverUser"
|
||||
placeholder="e.g. 1234567890"
|
||||
placeholder={t('Settings.Notifications.AddNotification.Pushover.UserPlaceholder')}
|
||||
onChange={(e) => setPushoverUser(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
@@ -668,8 +641,8 @@ export default function Settings() {
|
||||
</div>
|
||||
</AlertDialogDescription>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={addNotification}>Add</AlertDialogAction>
|
||||
<AlertDialogCancel>{t('Common.cancel')}</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={addNotification}>{t('Common.add')}</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
@@ -677,65 +650,63 @@ export default function Settings() {
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button className="w-full h-11" variant="outline">
|
||||
Customize Notification Text
|
||||
{t('Settings.Notifications.CustomizeText.Display')}
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogTitle>Customize Notification Text</AlertDialogTitle>
|
||||
<AlertDialogTitle>{t('Settings.Notifications.CustomizeText.Title')}</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-1.5">
|
||||
<Label htmlFor="text_application">Notification Text for Applications</Label>
|
||||
<Label>{t('Settings.Notifications.CustomizeText.Application')}</Label>
|
||||
<Textarea
|
||||
id="text_application"
|
||||
placeholder="Type here..."
|
||||
value={notificationTextApplication}
|
||||
onChange={(e) => setNotificationTextApplication(e.target.value)}
|
||||
rows={4}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label htmlFor="text_server">Notification Text for Servers</Label>
|
||||
<Label>{t('Settings.Notifications.CustomizeText.Server')}</Label>
|
||||
<Textarea
|
||||
id="text_server"
|
||||
placeholder="Type here..."
|
||||
value={notificationTextServer}
|
||||
onChange={(e) => setNotificationTextServer(e.target.value)}
|
||||
rows={4}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pt-4 text-sm text-muted-foreground">
|
||||
You can use the following placeholders in the text:
|
||||
<ul className="list-disc list-inside space-y-1 pt-2">
|
||||
<li>
|
||||
<b>Server related:</b>
|
||||
<div className="pt-4 text-sm text-muted-foreground">
|
||||
{t('Settings.Notifications.CustomizeText.Placeholders.Title')}
|
||||
<ul className="list-disc list-inside space-y-1 pt-2">
|
||||
<li>
|
||||
<b>{t('Settings.Notifications.CustomizeText.Placeholders.Server.Title')}</b>
|
||||
<ul className="list-disc list-inside ml-4 space-y-1 pt-1 text-muted-foreground">
|
||||
<li>!name - The name of the server</li>
|
||||
<li>!status - The current status of the server (online/offline)</li>
|
||||
<li>{t('Settings.Notifications.CustomizeText.Placeholders.Server.Name')}</li>
|
||||
<li>{t('Settings.Notifications.CustomizeText.Placeholders.Server.Status')}</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<b>Application related:</b>
|
||||
</li>
|
||||
<li>
|
||||
<b>{t('Settings.Notifications.CustomizeText.Placeholders.Application.Title')}</b>
|
||||
<ul className="list-disc list-inside ml-4 space-y-1 pt-1 text-muted-foreground">
|
||||
<li>!name - The name of the application</li>
|
||||
<li>!url - The URL where the application is hosted</li>
|
||||
<li>!status - The current status of the application (online/offline)</li>
|
||||
<li>{t('Settings.Notifications.CustomizeText.Placeholders.Application.Name')}</li>
|
||||
<li>{t('Settings.Notifications.CustomizeText.Placeholders.Application.Url')}</li>
|
||||
<li>{t('Settings.Notifications.CustomizeText.Placeholders.Application.Status')}</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</AlertDialogDescription>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={editNotificationText}>Save</AlertDialogAction>
|
||||
<AlertDialogCancel>{t('Common.cancel')}</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={editNotificationText}>
|
||||
{t('Common.Save')}
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
|
||||
<div className="mt-8">
|
||||
<h3 className="text-lg font-medium mb-4">Active Notification Channels</h3>
|
||||
<h3 className="text-lg font-medium mb-4">{t('Settings.Notifications.ActiveChannels')}</h3>
|
||||
<div className="space-y-3">
|
||||
{notifications.length > 0 ? (
|
||||
notifications.map((notification) => (
|
||||
@@ -775,14 +746,12 @@ export default function Settings() {
|
||||
</div>
|
||||
)}
|
||||
<div className="space-y-1">
|
||||
<h3 className="font-medium capitalize">{notification.name && notification.name !== "" ? notification.name : notification.type}</h3>
|
||||
<h3 className="font-medium capitalize">
|
||||
{notification.name ||
|
||||
t(`Settings.Notifications.AddNotification.${notification.type.charAt(0).toUpperCase() + notification.type.slice(1)}.Title`)}
|
||||
</h3>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{notification.type === "smtp" && "Email notifications"}
|
||||
{notification.type === "telegram" && "Telegram bot alerts"}
|
||||
{notification.type === "discord" && "Discord webhook alerts"}
|
||||
{notification.type === "gotify" && "Gotify notifications"}
|
||||
{notification.type === "ntfy" && "Ntfy notifications"}
|
||||
{notification.type === "pushover" && "Pushover notifications"}
|
||||
{t(`Settings.Notifications.AddNotification.${notification.type.charAt(0).toUpperCase() + notification.type.slice(1)}.Description`)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -794,7 +763,7 @@ export default function Settings() {
|
||||
onClick={() => testNotification(notification.id)}
|
||||
>
|
||||
<Play className="h-4 w-4 mr-1" />
|
||||
Test
|
||||
{t('Settings.Notifications.Test')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
@@ -803,6 +772,7 @@ export default function Settings() {
|
||||
onClick={() => deleteNotification(notification.id)}
|
||||
>
|
||||
<Trash2 className="h-4 w-4 mr-1" />
|
||||
{t('Settings.Notifications.Delete')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -814,9 +784,11 @@ export default function Settings() {
|
||||
<Bell className="h-6 w-6 text-muted-foreground" />
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg font-medium mb-1">No notifications configured</h3>
|
||||
<h3 className="text-lg font-medium mb-1">
|
||||
{t('Settings.Notifications.NoNotifications')}
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground max-w-md mx-auto">
|
||||
Add a notification channel to get alerted when your applications change status.
|
||||
{t('Settings.Notifications.NoNotificationsDescription')}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -830,4 +802,4 @@ export default function Settings() {
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user