mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-04-05 20:03:48 +00:00
Update notification service
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import { useState, useEffect, useCallback } from "react"
|
||||
import { useTheme } from "next-themes"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "./ui/card"
|
||||
import { Tabs, TabsList, TabsTrigger, TabsContent } from "./ui/tabs"
|
||||
import { Input } from "./ui/input"
|
||||
@@ -111,42 +112,54 @@ const AI_PROVIDERS = [
|
||||
label: "Groq",
|
||||
model: "llama-3.3-70b-versatile",
|
||||
description: "Very fast, generous free tier (30 req/min). Ideal to start.",
|
||||
keyUrl: "https://console.groq.com/keys"
|
||||
keyUrl: "https://console.groq.com/keys",
|
||||
icon: "/icons/Groq Logo_White 25.svg",
|
||||
iconLight: "/icons/Groq Logo_Black 25.svg"
|
||||
},
|
||||
{
|
||||
value: "openai",
|
||||
label: "OpenAI",
|
||||
model: "gpt-4o-mini",
|
||||
description: "Industry standard. Very accurate and widely used.",
|
||||
keyUrl: "https://platform.openai.com/api-keys"
|
||||
keyUrl: "https://platform.openai.com/api-keys",
|
||||
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/openai.png",
|
||||
iconLight: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/openai-light.png"
|
||||
},
|
||||
{
|
||||
value: "anthropic",
|
||||
label: "Anthropic (Claude)",
|
||||
model: "claude-3-haiku-20240307",
|
||||
description: "Excellent for writing and translation. Fast and economical.",
|
||||
keyUrl: "https://console.anthropic.com/settings/keys"
|
||||
keyUrl: "https://console.anthropic.com/settings/keys",
|
||||
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/anthropic.png",
|
||||
iconLight: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/anthropic-light.png"
|
||||
},
|
||||
{
|
||||
value: "gemini",
|
||||
label: "Google Gemini",
|
||||
model: "gemini-1.5-flash",
|
||||
description: "Free tier available, great quality/price ratio.",
|
||||
keyUrl: "https://aistudio.google.com/app/apikey"
|
||||
keyUrl: "https://aistudio.google.com/app/apikey",
|
||||
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/google-gemini.png",
|
||||
iconLight: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/google-gemini.png"
|
||||
},
|
||||
{
|
||||
value: "ollama",
|
||||
label: "Ollama (Local)",
|
||||
model: "llama3.2",
|
||||
description: "100% local execution. No costs, total privacy, no internet required.",
|
||||
keyUrl: ""
|
||||
keyUrl: "",
|
||||
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/ollama.png",
|
||||
iconLight: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/ollama.png"
|
||||
},
|
||||
{
|
||||
value: "openrouter",
|
||||
label: "OpenRouter",
|
||||
model: "meta-llama/llama-3.3-70b-instruct",
|
||||
description: "Aggregator with access to 100+ models using a single API key. Maximum flexibility.",
|
||||
keyUrl: "https://openrouter.ai/keys"
|
||||
keyUrl: "https://openrouter.ai/keys",
|
||||
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/openrouter.png",
|
||||
iconLight: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/openrouter.png"
|
||||
},
|
||||
]
|
||||
|
||||
@@ -213,6 +226,7 @@ const DEFAULT_CONFIG: NotificationConfig = {
|
||||
}
|
||||
|
||||
export function NotificationSettings() {
|
||||
const { resolvedTheme } = useTheme()
|
||||
const [config, setConfig] = useState<NotificationConfig>(DEFAULT_CONFIG)
|
||||
const [status, setStatus] = useState<ServiceStatus | null>(null)
|
||||
const [history, setHistory] = useState<HistoryEntry[]>([])
|
||||
@@ -1312,11 +1326,11 @@ export function NotificationSettings() {
|
||||
</button>
|
||||
|
||||
{showAdvanced && (
|
||||
<div className="space-y-3 mt-3 p-3 rounded-lg bg-muted/30 border border-border/50">
|
||||
<div className="space-y-4 mt-3 p-4 rounded-lg bg-muted/30 border border-border/50">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<span className="text-xs font-medium">AI-Enhanced Messages</span>
|
||||
<p className="text-[10px] text-muted-foreground">Use AI to generate contextual notification messages</p>
|
||||
<span className="text-sm font-medium">AI-Enhanced Messages</span>
|
||||
<p className="text-xs sm:text-sm text-muted-foreground">Use AI to generate contextual notification messages</p>
|
||||
</div>
|
||||
<button
|
||||
className={`relative w-9 h-[18px] rounded-full transition-colors ${
|
||||
@@ -1411,28 +1425,26 @@ export function NotificationSettings() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Model (optional) */}
|
||||
{/* Model (read-only display) */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs sm:text-sm text-muted-foreground">Model (optional)</Label>
|
||||
<Input
|
||||
className="h-9 text-sm font-mono"
|
||||
placeholder={AI_PROVIDERS.find(p => p.value === config.ai_provider)?.model || ""}
|
||||
value={config.ai_model}
|
||||
onChange={e => updateConfig(p => ({ ...p, ai_model: e.target.value }))}
|
||||
disabled={!editMode}
|
||||
/>
|
||||
<Label className="text-xs sm:text-sm text-muted-foreground">Model</Label>
|
||||
<div className="h-9 px-3 flex items-center rounded-md border border-border bg-muted/50 text-sm font-mono text-muted-foreground">
|
||||
{AI_PROVIDERS.find(p => p.value === config.ai_provider)?.model || "default"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Language selector */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs sm:text-sm text-muted-foreground">Language</Label>
|
||||
<Select
|
||||
value={config.ai_language}
|
||||
value={config.ai_language || "en"}
|
||||
onValueChange={v => updateConfig(p => ({ ...p, ai_language: v }))}
|
||||
disabled={!editMode}
|
||||
>
|
||||
<SelectTrigger className="h-9 text-sm">
|
||||
<SelectValue />
|
||||
<SelectValue placeholder="Select language">
|
||||
{AI_LANGUAGES.find(l => l.value === (config.ai_language || "en"))?.label || "English"}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{AI_LANGUAGES.map(l => (
|
||||
@@ -1536,7 +1548,7 @@ export function NotificationSettings() {
|
||||
|
||||
{/* AI Provider Information Modal */}
|
||||
<Dialog open={showProviderInfo} onOpenChange={setShowProviderInfo}>
|
||||
<DialogContent className="max-w-md">
|
||||
<DialogContent className="max-w-md sm:max-w-lg md:max-w-xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-base sm:text-lg">AI Providers Information</DialogTitle>
|
||||
</DialogHeader>
|
||||
@@ -1547,15 +1559,29 @@ export function NotificationSettings() {
|
||||
className="p-4 rounded-lg bg-muted/50 border border-border hover:border-muted-foreground/40 transition-colors"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-medium text-sm sm:text-base">{provider.label}</span>
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Provider icon with theme support */}
|
||||
<div className="w-8 h-8 rounded-md bg-background flex items-center justify-center border border-border shrink-0">
|
||||
<img
|
||||
src={resolvedTheme === 'light' ? provider.iconLight : provider.icon}
|
||||
alt={provider.label}
|
||||
className="w-5 h-5 object-contain"
|
||||
onError={(e) => {
|
||||
// Fallback if icon fails to load
|
||||
(e.target as HTMLImageElement).style.display = 'none'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="font-medium text-sm sm:text-base">{provider.label}</span>
|
||||
</div>
|
||||
{provider.value === "ollama" && (
|
||||
<Badge variant="outline" className="text-xs px-2 py-0.5">Local</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-xs sm:text-sm text-muted-foreground mt-1.5">
|
||||
<div className="text-xs sm:text-sm text-muted-foreground mt-2 ml-11">
|
||||
Default model: <code className="text-xs bg-muted px-1.5 py-0.5 rounded font-mono">{provider.model}</code>
|
||||
</div>
|
||||
<p className="text-xs sm:text-sm text-muted-foreground mt-2 leading-relaxed">
|
||||
<p className="text-xs sm:text-sm text-muted-foreground mt-2 ml-11 leading-relaxed">
|
||||
{provider.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
10
AppImage/public/icons/Groq Logo_Black 25.svg
Normal file
10
AppImage/public/icons/Groq Logo_Black 25.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200.18 69.76">
|
||||
<g id="Layer_1-2" data-name="Layer 1">
|
||||
<path d="M114.26.13c-13.19,0-23.88,10.68-23.88,23.88s10.68,23.9,23.88,23.9,23.88-10.68,23.88-23.88h0c-.02-13.19-10.71-23.88-23.88-23.9ZM114.26,38.94c-8.24,0-14.93-6.69-14.93-14.93s6.69-14.93,14.93-14.93,14.93,6.69,14.93,14.93c-.02,8.24-6.71,14.93-14.93,14.93h0Z"/>
|
||||
<path d="M24.11,0C10.92-.11.13,10.47,0,23.66c-.13,13.19,10.47,23.98,23.66,24.11h8.31v-8.94h-7.86c-8.24.11-15-6.5-15.1-14.74-.11-8.24,6.5-15,14.74-15.1h.34c8.22,0,14.95,6.69,14.95,14.93h0v21.98h0c0,8.18-6.65,14.83-14.81,14.93-3.91-.04-7.63-1.59-10.39-4.38l-6.33,6.31c4.4,4.42,10.34,6.92,16.57,6.99h.32c13.02-.19,23.49-10.75,23.56-23.77v-22.69C47.65,10.35,37.05.02,24.11,0Z"/>
|
||||
<path d="M191.28,68.74V23.43c-.32-12.96-10.92-23.28-23.88-23.3-13.19-.13-23.98,10.47-24.11,23.66-.13,13.19,10.49,23.98,23.68,24.11h8.31v-8.94h-7.86c-8.24.11-15-6.5-15.1-14.74s6.5-15,14.74-15.1h.34c8.22,0,14.95,6.69,14.95,14.93h0v44.63h0l8.92.06Z"/>
|
||||
<path d="M54.8,47.9h8.92v-23.88c0-8.24,6.69-14.93,14.93-14.93,2.72,0,5.25.72,7.46,2l4.48-7.75c-3.5-2.02-7.58-3.19-11.92-3.19-13.19,0-23.88,10.68-23.88,23.88v23.88Z"/>
|
||||
<path d="M198.01.74c.68.38,1.21.91,1.59,1.59.38.68.57,1.42.57,2.25s-.19,1.57-.59,2.27c-.4.68-.93,1.23-1.61,1.61-.68.4-1.44.59-2.25.59s-1.57-.19-2.25-.59c-.68-.4-1.21-.93-1.59-1.61-.38-.68-.59-1.42-.59-2.25s.19-1.57.59-2.25c.38-.68.93-1.21,1.61-1.61s1.44-.59,2.27-.59c.83,0,1.57.19,2.25.59ZM197.57,7.75c.55-.32.98-.76,1.3-1.32.32-.55.47-1.17.47-1.85s-.15-1.3-.47-1.85-.74-.98-1.27-1.3c-.55-.32-1.17-.47-1.85-.47s-1.3.17-1.85.49c-.55.32-.98.76-1.3,1.32s-.47,1.17-.47,1.85.15,1.3.47,1.85c.32.55.74,1,1.27,1.32.55.32,1.15.49,1.83.49.7-.04,1.32-.21,1.87-.53ZM197.84,4.82c-.15.25-.38.45-.68.59l1.06,1.64h-1.32l-.91-1.42h-.87v1.42h-1.32V2.17h2.12c.66,0,1.19.15,1.57.47.38.32.57.74.57,1.27,0,.34-.08.66-.23.91ZM195.85,4.65c.3,0,.53-.06.68-.19.17-.13.25-.32.25-.55s-.08-.42-.25-.57-.4-.19-.68-.19h-.74v1.53h.74v-.02Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
17
AppImage/public/icons/Groq Logo_White 25.svg
Normal file
17
AppImage/public/icons/Groq Logo_White 25.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200.18 69.76">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #fff;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1-2" data-name="Layer 1">
|
||||
<path class="cls-1" d="M114.26.13c-13.19,0-23.88,10.68-23.88,23.88s10.68,23.9,23.88,23.9,23.88-10.68,23.88-23.88h0c-.02-13.19-10.71-23.88-23.88-23.9ZM114.26,38.94c-8.24,0-14.93-6.69-14.93-14.93s6.69-14.93,14.93-14.93,14.93,6.69,14.93,14.93c-.02,8.24-6.71,14.93-14.93,14.93h0Z"/>
|
||||
<path class="cls-1" d="M24.11,0C10.92-.11.13,10.47,0,23.66c-.13,13.19,10.47,23.98,23.66,24.11h8.31v-8.94h-7.86c-8.24.11-15-6.5-15.1-14.74-.11-8.24,6.5-15,14.74-15.1h.34c8.22,0,14.95,6.69,14.95,14.93h0v21.98h0c0,8.18-6.65,14.83-14.81,14.93-3.91-.04-7.63-1.59-10.39-4.38l-6.33,6.31c4.4,4.42,10.34,6.92,16.57,6.99h.32c13.02-.19,23.49-10.75,23.56-23.77v-22.69C47.65,10.35,37.05.02,24.11,0Z"/>
|
||||
<path class="cls-1" d="M191.28,68.74V23.43c-.32-12.96-10.92-23.28-23.88-23.3-13.19-.13-23.98,10.47-24.11,23.66-.13,13.19,10.49,23.98,23.68,24.11h8.31v-8.94h-7.86c-8.24.11-15-6.5-15.1-14.74s6.5-15,14.74-15.1h.34c8.22,0,14.95,6.69,14.95,14.93h0v44.63h0l8.92.06Z"/>
|
||||
<path class="cls-1" d="M54.8,47.9h8.92v-23.88c0-8.24,6.69-14.93,14.93-14.93,2.72,0,5.25.72,7.46,2l4.48-7.75c-3.5-2.02-7.58-3.19-11.92-3.19-13.19,0-23.88,10.68-23.88,23.88v23.88Z"/>
|
||||
<path class="cls-1" d="M198.01.74c.68.38,1.21.91,1.59,1.59.38.68.57,1.42.57,2.25s-.19,1.57-.59,2.27c-.4.68-.93,1.23-1.61,1.61-.68.4-1.44.59-2.25.59s-1.57-.19-2.25-.59c-.68-.4-1.21-.93-1.59-1.61-.38-.68-.59-1.42-.59-2.25s.19-1.57.59-2.25c.38-.68.93-1.21,1.61-1.61s1.44-.59,2.27-.59c.83,0,1.57.19,2.25.59ZM197.57,7.75c.55-.32.98-.76,1.3-1.32.32-.55.47-1.17.47-1.85s-.15-1.3-.47-1.85-.74-.98-1.27-1.3c-.55-.32-1.17-.47-1.85-.47s-1.3.17-1.85.49c-.55.32-.98.76-1.3,1.32s-.47,1.17-.47,1.85.15,1.3.47,1.85c.32.55.74,1,1.27,1.32.55.32,1.15.49,1.83.49.7-.04,1.32-.21,1.87-.53ZM197.84,4.82c-.15.25-.38.45-.68.59l1.06,1.64h-1.32l-.91-1.42h-.87v1.42h-1.32V2.17h2.12c.66,0,1.19.15,1.57.47.38.32.57.74.57,1.27,0,.34-.08.66-.23.91ZM195.85,4.65c.3,0,.53-.06.68-.19.17-.13.25-.32.25-.55s-.08-.42-.25-.57-.4-.19-.68-.19h-.74v1.53h.74v-.02Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -100,7 +100,7 @@ def generate_description(
|
||||
<table style='width: 100%; border-collapse: collapse;'>
|
||||
<tr>
|
||||
<td style='width: 100px; vertical-align: middle;'>
|
||||
<img src='https://raw.githubusercontent.com/MacRimi/ProxMenux/main/images/logo_desc.png' alt='ProxMenux Logo' style='height: 100px;'>
|
||||
<img src="/images/design-mode/logo_desc.png" alt='ProxMenux Logo' style='height: 100px;'>
|
||||
</td>
|
||||
<td style='vertical-align: middle;'>
|
||||
<h1 style='margin: 0;'>{app_name}</h1>
|
||||
@@ -186,7 +186,7 @@ def generate_vm_description(
|
||||
<table style='width: 100%; border-collapse: collapse;'>
|
||||
<tr>
|
||||
<td style='width: 100px; vertical-align: middle;'>
|
||||
<img src='https://raw.githubusercontent.com/MacRimi/ProxMenux/main/images/logo_desc.png' alt='ProxMenux Logo' style='height: 100px;'>
|
||||
<img src="/images/design-mode/logo_desc.png" alt='ProxMenux Logo' style='height: 100px;'>
|
||||
</td>
|
||||
<td style='vertical-align: middle;'>
|
||||
<h1 style='margin: 0;'>{vm_name}</h1>
|
||||
|
||||
@@ -1071,7 +1071,7 @@ def _generate_html_description(app_def: Dict, container_def: Dict, hostname: str
|
||||
<table style='width: 100%; border-collapse: collapse;'>
|
||||
<tr>
|
||||
<td style='width: 100px; vertical-align: middle;'>
|
||||
<img src='https://raw.githubusercontent.com/MacRimi/ProxMenux/main/images/logo_desc.png' alt='ProxMenux Logo' style='height: 100px;'>
|
||||
<img src="/images/design-mode/logo_desc.png" alt='ProxMenux Logo' style='height: 100px;'>
|
||||
</td>
|
||||
<td style='vertical-align: middle;'>
|
||||
<h1 style='margin: 0;'>{app_name}</h1>
|
||||
|
||||
Reference in New Issue
Block a user